[Intl] Refactored Locale component into two new components Icu and Intl
This commit is contained in:
parent
a7c9863b3a
commit
5917a2e0cb
@ -14,5 +14,3 @@ before_script:
|
|||||||
- echo '' > ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini
|
- echo '' > ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini
|
||||||
- echo "extension = apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
- echo "extension = apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||||
- COMPOSER_ROOT_VERSION=dev-master composer --prefer-source --dev install
|
- COMPOSER_ROOT_VERSION=dev-master composer --prefer-source --dev install
|
||||||
- php src/Symfony/Component/Locale/Resources/data/build-data.php
|
|
||||||
- export USE_INTL_ICU_DATA_VERSION=1
|
|
||||||
|
@ -10,8 +10,4 @@ $loader = require_once __DIR__.'/vendor/autoload.php';
|
|||||||
|
|
||||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||||
|
|
||||||
if (!function_exists('intl_get_error_code')) {
|
|
||||||
require_once __DIR__.'/src/Symfony/Component/Locale/Resources/stubs/functions.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
|
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.3",
|
"php": ">=5.3.3",
|
||||||
|
"symfony/icu": ">=1.0",
|
||||||
"doctrine/common": "~2.2",
|
"doctrine/common": "~2.2",
|
||||||
"twig/twig": "~1.11",
|
"twig/twig": "~1.11",
|
||||||
"psr/log": "~1.0"
|
"psr/log": "~1.0"
|
||||||
@ -37,6 +38,7 @@
|
|||||||
"symfony/framework-bundle": "self.version",
|
"symfony/framework-bundle": "self.version",
|
||||||
"symfony/http-foundation": "self.version",
|
"symfony/http-foundation": "self.version",
|
||||||
"symfony/http-kernel": "self.version",
|
"symfony/http-kernel": "self.version",
|
||||||
|
"symfony/intl": "self.version",
|
||||||
"symfony/locale": "self.version",
|
"symfony/locale": "self.version",
|
||||||
"symfony/monolog-bridge": "self.version",
|
"symfony/monolog-bridge": "self.version",
|
||||||
"symfony/options-resolver": "self.version",
|
"symfony/options-resolver": "self.version",
|
||||||
@ -68,8 +70,9 @@
|
|||||||
"psr-0": { "Symfony\\": "src/" },
|
"psr-0": { "Symfony\\": "src/" },
|
||||||
"classmap": [
|
"classmap": [
|
||||||
"src/Symfony/Component/HttpFoundation/Resources/stubs",
|
"src/Symfony/Component/HttpFoundation/Resources/stubs",
|
||||||
"src/Symfony/Component/Locale/Resources/stubs"
|
"src/Symfony/Component/Intl/Resources/stubs"
|
||||||
]
|
],
|
||||||
|
"files": [ "src/Symfony/Component/Intl/Resources/stubs/functions.php" ]
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"extra": {
|
"extra": {
|
||||||
|
3
src/Symfony/Component/Intl/.gitignore
vendored
Normal file
3
src/Symfony/Component/Intl/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
vendor/
|
||||||
|
composer.lock
|
||||||
|
phpunit.xml
|
91
src/Symfony/Component/Intl/CONTRIBUTING.md
Normal file
91
src/Symfony/Component/Intl/CONTRIBUTING.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
Contributing to the Intl component
|
||||||
|
==================================
|
||||||
|
|
||||||
|
A very good way of contributing to the Intl component is by updating the
|
||||||
|
included data for the ICU version you have installed on your system.
|
||||||
|
|
||||||
|
Preparation
|
||||||
|
-----------
|
||||||
|
|
||||||
|
To prepare, you need to install the development dependencies of the component.
|
||||||
|
|
||||||
|
$ cd /path/to/Symfony/Component/Intl
|
||||||
|
$ composer.phar install --dev
|
||||||
|
|
||||||
|
Determining your ICU version
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The ICU version installed in your PHP environment can be found by running
|
||||||
|
icu-version.php:
|
||||||
|
|
||||||
|
$ php Resources/bin/icu-version.php
|
||||||
|
|
||||||
|
Updating the ICU data
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
To update the data files, run the update-icu-component.php script:
|
||||||
|
|
||||||
|
$ php Resources/bin/update-icu-component.php
|
||||||
|
|
||||||
|
The script needs the binaries "svn" and "make" to be available on your system.
|
||||||
|
It will download the latest version of the ICU sources for the ICU version
|
||||||
|
installed in your PHP environment. The script will then compile the "genrb"
|
||||||
|
binary and use it to compile the ICU data files to binaries. The binaries are
|
||||||
|
copied to the Resources/ directory of the Icu component found in the
|
||||||
|
vendor/symfony/icu/ directory.
|
||||||
|
|
||||||
|
Updating the stub data
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
In the previous step you updated the Icu component for the ICU version
|
||||||
|
installed on your system. If you are using the latest ICU version, you should
|
||||||
|
also create the stub data files which will be used by people who don't have
|
||||||
|
the intl extension installed.
|
||||||
|
|
||||||
|
To update the stub files, run the update-stubs.php script:
|
||||||
|
|
||||||
|
$ php Resources/bin/update-stubs.php
|
||||||
|
|
||||||
|
The script will fail if you don't have the latest ICU version. If you want to
|
||||||
|
upgrade the ICU version, adjust the return value of the
|
||||||
|
`Intl::getStubIcuVersion()` before you run the script.
|
||||||
|
|
||||||
|
The script creates copies of the binary resource bundles in the Icu component
|
||||||
|
and stores them in the Resources/ directory of the Intl component. The copies
|
||||||
|
are made for the locale "en" only and are stored in .php files, so that they
|
||||||
|
can be read even if the intl extension is not available.
|
||||||
|
|
||||||
|
Creating a pull request
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
You need to create up to two pull requests:
|
||||||
|
|
||||||
|
* If you updated the Icu component, you need to push that change and create a
|
||||||
|
pull request in the `symfony/Icu` repository. Make sure to submit the pull
|
||||||
|
request to the correct master branch. If you updated the ICU data for version
|
||||||
|
4.8, your pull request goes to branch `48-master`, for version 49 to
|
||||||
|
`49-master` and so on.
|
||||||
|
|
||||||
|
* If you updated the stub files of the Intl component, you need to push that
|
||||||
|
change and create a pull request in the `symfony/symfony` repository. The
|
||||||
|
pull request should be based on the `master` branch.
|
||||||
|
|
||||||
|
Combining .res files to a .dat-package
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
The individual *.res files can be combined into a single .dat-file.
|
||||||
|
Unfortunately, PHP's `ResourceBundle` class is currently not able to handle
|
||||||
|
.dat-files.
|
||||||
|
|
||||||
|
Once it is, the following steps have to be followed to build the .dat-file:
|
||||||
|
|
||||||
|
1. Package the resource bundles into a single file
|
||||||
|
|
||||||
|
$ find . -name *.res | sed -e "s/\.\///g" > packagelist.txt
|
||||||
|
$ pkgdata -p region -T build -d . packagelist.txt
|
||||||
|
|
||||||
|
2. Clean up
|
||||||
|
|
||||||
|
$ rm -rf build packagelist.txt
|
||||||
|
|
||||||
|
3. You can now move region.dat to replace the version bundled with Symfony2.
|
284
src/Symfony/Component/Intl/Collator/StubCollator.php
Normal file
284
src/Symfony/Component/Intl/Collator/StubCollator.php
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Collator;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\MethodNotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Globals\StubIntlGlobals;
|
||||||
|
use Symfony\Component\Intl\Locale\StubLocale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a stub Collator for the 'en' locale.
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class StubCollator
|
||||||
|
{
|
||||||
|
/** Attribute constants */
|
||||||
|
const FRENCH_COLLATION = 0;
|
||||||
|
const ALTERNATE_HANDLING = 1;
|
||||||
|
const CASE_FIRST = 2;
|
||||||
|
const CASE_LEVEL = 3;
|
||||||
|
const NORMALIZATION_MODE = 4;
|
||||||
|
const STRENGTH = 5;
|
||||||
|
const HIRAGANA_QUATERNARY_MODE = 6;
|
||||||
|
const NUMERIC_COLLATION = 7;
|
||||||
|
|
||||||
|
/** Attribute constants values */
|
||||||
|
const DEFAULT_VALUE = -1;
|
||||||
|
|
||||||
|
const PRIMARY = 0;
|
||||||
|
const SECONDARY = 1;
|
||||||
|
const TERTIARY = 2;
|
||||||
|
const DEFAULT_STRENGTH = 2;
|
||||||
|
const QUATERNARY = 3;
|
||||||
|
const IDENTICAL = 15;
|
||||||
|
|
||||||
|
const OFF = 16;
|
||||||
|
const ON = 17;
|
||||||
|
|
||||||
|
const SHIFTED = 20;
|
||||||
|
const NON_IGNORABLE = 21;
|
||||||
|
|
||||||
|
const LOWER_FIRST = 24;
|
||||||
|
const UPPER_FIRST = 25;
|
||||||
|
|
||||||
|
/** Sorting options */
|
||||||
|
const SORT_REGULAR = 0;
|
||||||
|
const SORT_NUMERIC = 2;
|
||||||
|
const SORT_STRING = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When $locale different than 'en' is passed
|
||||||
|
*/
|
||||||
|
public function __construct($locale)
|
||||||
|
{
|
||||||
|
if ('en' != $locale) {
|
||||||
|
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'locale', $locale, 'Only the \'en\' locale is supported');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static constructor
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code
|
||||||
|
*
|
||||||
|
* @return StubCollator
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When $locale different than 'en' is passed
|
||||||
|
*/
|
||||||
|
public static function create($locale)
|
||||||
|
{
|
||||||
|
return new self($locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort array maintaining index association
|
||||||
|
*
|
||||||
|
* @param array &$array Input array
|
||||||
|
* @param integer $sortFlag Flags for sorting, can be one of the following:
|
||||||
|
* StubCollator::SORT_REGULAR - compare items normally (don't change types)
|
||||||
|
* StubCollator::SORT_NUMERIC - compare items numerically
|
||||||
|
* StubCollator::SORT_STRING - compare items as strings
|
||||||
|
*
|
||||||
|
* @return Boolean True on success or false on failure
|
||||||
|
*/
|
||||||
|
public function asort(&$array, $sortFlag = self::SORT_REGULAR)
|
||||||
|
{
|
||||||
|
$intlToPlainFlagMap = array(
|
||||||
|
self::SORT_REGULAR => \SORT_REGULAR,
|
||||||
|
self::SORT_NUMERIC => \SORT_NUMERIC,
|
||||||
|
self::SORT_STRING => \SORT_STRING,
|
||||||
|
);
|
||||||
|
|
||||||
|
$plainSortFlag = isset($intlToPlainFlagMap[$sortFlag]) ? $intlToPlainFlagMap[$sortFlag] : self::SORT_REGULAR;
|
||||||
|
|
||||||
|
return asort($array, $plainSortFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two Unicode strings
|
||||||
|
*
|
||||||
|
* @param string $str1 The first string to compare
|
||||||
|
* @param string $str2 The second string to compare
|
||||||
|
*
|
||||||
|
* @return Boolean|int Return the comparison result or false on failure:
|
||||||
|
* 1 if $str1 is greater than $str2
|
||||||
|
* 0 if $str1 is equal than $str2
|
||||||
|
* -1 if $str1 is less than $str2
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/collator.compare.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function compare($str1, $str2)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a value of an integer collator attribute
|
||||||
|
*
|
||||||
|
* @param int $attr An attribute specifier, one of the attribute constants
|
||||||
|
*
|
||||||
|
* @return Boolean|int The attribute value on success or false on error
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/collator.getattribute.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function getAttribute($attr)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns collator's last error code. Always returns the U_ZERO_ERROR class constant value
|
||||||
|
*
|
||||||
|
* @return int The error code from last collator call
|
||||||
|
*/
|
||||||
|
public function getErrorCode()
|
||||||
|
{
|
||||||
|
return StubIntlGlobals::U_ZERO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns collator's last error message. Always returns the U_ZERO_ERROR_MESSAGE class constant value
|
||||||
|
*
|
||||||
|
* @return string The error message from last collator call
|
||||||
|
*/
|
||||||
|
public function getErrorMessage()
|
||||||
|
{
|
||||||
|
return 'U_ZERO_ERROR';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the collator's locale
|
||||||
|
*
|
||||||
|
* @param int $type The locale name type to return between valid or actual (StubLocale::VALID_LOCALE or StubLocale::ACTUAL_LOCALE, respectively)
|
||||||
|
*
|
||||||
|
* @return string The locale name used to create the collator
|
||||||
|
*/
|
||||||
|
public function getLocale($type = StubLocale::ACTUAL_LOCALE)
|
||||||
|
{
|
||||||
|
return 'en';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sorting key for a string
|
||||||
|
*
|
||||||
|
* @param string $string The string to produce the key from
|
||||||
|
*
|
||||||
|
* @return string The collation key for $string
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/collator.getsortkey.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function getSortKey($string)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current collator's strength
|
||||||
|
*
|
||||||
|
* @return Boolean|int The current collator's strength or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/collator.getstrength.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function getStrength()
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a collator's attribute
|
||||||
|
*
|
||||||
|
* @param int $attr An attribute specifier, one of the attribute constants
|
||||||
|
* @param int $val The attribute value, one of the attribute value constants
|
||||||
|
*
|
||||||
|
* @return Boolean True on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/collator.setattribute.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function setAttribute($attr, $val)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the collator's strength
|
||||||
|
*
|
||||||
|
* @param int $strength Strength to set, possible values:
|
||||||
|
* StubCollator::PRIMARY
|
||||||
|
* StubCollator::SECONDARY
|
||||||
|
* StubCollator::TERTIARY
|
||||||
|
* StubCollator::QUATERNARY
|
||||||
|
* StubCollator::IDENTICAL
|
||||||
|
* StubCollator::DEFAULT
|
||||||
|
*
|
||||||
|
* @return Boolean True on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/collator.setstrength.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function setStrength($strength)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort array using specified collator and sort keys
|
||||||
|
*
|
||||||
|
* @param array &$arr Array of strings to sort
|
||||||
|
*
|
||||||
|
* @return Boolean True on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/collator.sortwithsortkeys.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function sortWithSortKeys(&$arr)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort array using specified collator
|
||||||
|
*
|
||||||
|
* @param array &$arr Array of string to sort
|
||||||
|
* @param int $sortFlag Optional sorting type, one of the following:
|
||||||
|
* StubCollator::SORT_REGULAR
|
||||||
|
* StubCollator::SORT_NUMERIC
|
||||||
|
* StubCollator::SORT_STRING
|
||||||
|
*
|
||||||
|
* @return Boolean True on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/collator.sort.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function sort(&$arr, $sortFlag = self::SORT_REGULAR)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for AM/PM markers format
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class AmPmTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
return $dateTime->format('A');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return 'AM|PM';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'marker' => $matched
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for day of week format
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class DayOfWeekTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
$dayOfWeek = $dateTime->format('l');
|
||||||
|
switch ($length) {
|
||||||
|
case 4:
|
||||||
|
return $dayOfWeek;
|
||||||
|
case 5:
|
||||||
|
return $dayOfWeek[0];
|
||||||
|
default:
|
||||||
|
return substr($dayOfWeek, 0, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
switch ($length) {
|
||||||
|
case 4:
|
||||||
|
return 'Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday';
|
||||||
|
case 5:
|
||||||
|
return '[MTWFS]';
|
||||||
|
default:
|
||||||
|
return 'Mon|Tue|Wed|Thu|Fri|Sat|Sun';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for day of year format
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class DayOfYearTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
$dayOfYear = $dateTime->format('z') + 1;
|
||||||
|
|
||||||
|
return $this->padLeft($dayOfYear, $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return '\d{'.$length.'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for day format
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class DayTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
return $this->padLeft($dateTime->format('j'), $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return 1 === $length ? '\d{1,2}' : '\d{'.$length.'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'day' => (int) $matched,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,356 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\NotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Globals\StubIntlGlobals;
|
||||||
|
use Symfony\Component\Intl\DateFormatter\DateFormat\MonthTransformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for date formats
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class FullTransformer
|
||||||
|
{
|
||||||
|
private $quoteMatch = "'(?:[^']+|'')*'";
|
||||||
|
private $implementedChars = 'MLydQqhDEaHkKmsz';
|
||||||
|
private $notImplementedChars = 'GYuwWFgecSAZvVW';
|
||||||
|
private $regExp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Transformer[]
|
||||||
|
*/
|
||||||
|
private $transformers;
|
||||||
|
|
||||||
|
private $pattern;
|
||||||
|
private $timezone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $pattern The pattern to be used to format and/or parse values
|
||||||
|
* @param string $timezone The timezone to perform the date/time calculations
|
||||||
|
*/
|
||||||
|
public function __construct($pattern, $timezone)
|
||||||
|
{
|
||||||
|
$this->pattern = $pattern;
|
||||||
|
$this->timezone = $timezone;
|
||||||
|
|
||||||
|
$implementedCharsMatch = $this->buildCharsMatch($this->implementedChars);
|
||||||
|
$notImplementedCharsMatch = $this->buildCharsMatch($this->notImplementedChars);
|
||||||
|
$this->regExp = "/($this->quoteMatch|$implementedCharsMatch|$notImplementedCharsMatch)/";
|
||||||
|
|
||||||
|
$this->transformers = array(
|
||||||
|
'M' => new MonthTransformer(),
|
||||||
|
'L' => new MonthTransformer(),
|
||||||
|
'y' => new YearTransformer(),
|
||||||
|
'd' => new DayTransformer(),
|
||||||
|
'q' => new QuarterTransformer(),
|
||||||
|
'Q' => new QuarterTransformer(),
|
||||||
|
'h' => new Hour1201Transformer(),
|
||||||
|
'D' => new DayOfYearTransformer(),
|
||||||
|
'E' => new DayOfWeekTransformer(),
|
||||||
|
'a' => new AmPmTransformer(),
|
||||||
|
'H' => new Hour2400Transformer(),
|
||||||
|
'K' => new Hour1200Transformer(),
|
||||||
|
'k' => new Hour2401Transformer(),
|
||||||
|
'm' => new MinuteTransformer(),
|
||||||
|
's' => new SecondTransformer(),
|
||||||
|
'z' => new TimeZoneTransformer(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the array of Transformer objects
|
||||||
|
*
|
||||||
|
* @return Transformer[] Associative array of Transformer objects (format char => Transformer)
|
||||||
|
*/
|
||||||
|
public function getTransformers()
|
||||||
|
{
|
||||||
|
return $this->transformers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a DateTime using ICU dateformat pattern
|
||||||
|
*
|
||||||
|
* @param \DateTime $dateTime A DateTime object to be used to generate the formatted value
|
||||||
|
*
|
||||||
|
* @return string The formatted value
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime)
|
||||||
|
{
|
||||||
|
$that = $this;
|
||||||
|
|
||||||
|
$formatted = preg_replace_callback($this->regExp, function($matches) use ($that, $dateTime) {
|
||||||
|
return $that->formatReplace($matches[0], $dateTime);
|
||||||
|
}, $this->pattern);
|
||||||
|
|
||||||
|
return $formatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the formatted ICU value for the matched date characters
|
||||||
|
*
|
||||||
|
* @param string $dateChars The date characters to be replaced with a formatted ICU value
|
||||||
|
* @param DateTime $dateTime A DateTime object to be used to generate the formatted value
|
||||||
|
*
|
||||||
|
* @return string The formatted value
|
||||||
|
*
|
||||||
|
* @throws NotImplementedException When it encounters a not implemented date character
|
||||||
|
*/
|
||||||
|
public function formatReplace($dateChars, $dateTime)
|
||||||
|
{
|
||||||
|
$length = strlen($dateChars);
|
||||||
|
|
||||||
|
if ($this->isQuoteMatch($dateChars)) {
|
||||||
|
return $this->replaceQuoteMatch($dateChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->transformers[$dateChars[0]])) {
|
||||||
|
$transformer = $this->transformers[$dateChars[0]];
|
||||||
|
|
||||||
|
return $transformer->format($dateTime, $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle unimplemented characters
|
||||||
|
if (false !== strpos($this->notImplementedChars, $dateChars[0])) {
|
||||||
|
throw new NotImplementedException(sprintf("Unimplemented date character '%s' in format '%s'", $dateChars[0], $this->pattern));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a pattern based string to a timestamp value
|
||||||
|
*
|
||||||
|
* @param \DateTime $dateTime A configured DateTime object to use to perform the date calculation
|
||||||
|
* @param string $value String to convert to a time value
|
||||||
|
*
|
||||||
|
* @return int The corresponding Unix timestamp
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException When the value can not be matched with pattern
|
||||||
|
*/
|
||||||
|
public function parse(\DateTime $dateTime, $value)
|
||||||
|
{
|
||||||
|
$reverseMatchingRegExp = $this->getReverseMatchingRegExp($this->pattern);
|
||||||
|
$reverseMatchingRegExp = '/^'.$reverseMatchingRegExp.'$/';
|
||||||
|
|
||||||
|
$options = array();
|
||||||
|
|
||||||
|
if (preg_match($reverseMatchingRegExp, $value, $matches)) {
|
||||||
|
$matches = $this->normalizeArray($matches);
|
||||||
|
|
||||||
|
foreach ($this->transformers as $char => $transformer) {
|
||||||
|
if (isset($matches[$char])) {
|
||||||
|
$length = strlen($matches[$char]['pattern']);
|
||||||
|
$options = array_merge($options, $transformer->extractDateOptions($matches[$char]['value'], $length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset error code and message
|
||||||
|
StubIntlGlobals::setError(StubIntlGlobals::U_ZERO_ERROR);
|
||||||
|
|
||||||
|
return $this->calculateUnixTimestamp($dateTime, $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// behave like the intl extension
|
||||||
|
StubIntlGlobals::setError(StubIntlGlobals::U_PARSE_ERROR, 'Date parsing failed');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a regular expression to match with a formatted value.
|
||||||
|
*
|
||||||
|
* @param string $pattern The pattern to create the reverse matching regular expression
|
||||||
|
*
|
||||||
|
* @return string The reverse matching regular expression with named captures being formed by the
|
||||||
|
* transformer index in the $transformer array
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($pattern)
|
||||||
|
{
|
||||||
|
$that = $this;
|
||||||
|
|
||||||
|
$escapedPattern = preg_quote($pattern, '/');
|
||||||
|
|
||||||
|
// ICU 4.8 recognizes slash ("/") in a value to be parsed as a dash ("-") and vice-versa
|
||||||
|
// when parsing a date/time value
|
||||||
|
$escapedPattern = preg_replace('/\\\[\-|\/]/', '[\/\-]', $escapedPattern);
|
||||||
|
|
||||||
|
$reverseMatchingRegExp = preg_replace_callback($this->regExp, function($matches) use ($that) {
|
||||||
|
$length = strlen($matches[0]);
|
||||||
|
$transformerIndex = $matches[0][0];
|
||||||
|
|
||||||
|
$dateChars = $matches[0];
|
||||||
|
if ($that->isQuoteMatch($dateChars)) {
|
||||||
|
return $that->replaceQuoteMatch($dateChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
$transformers = $that->getTransformers();
|
||||||
|
if (isset($transformers[$transformerIndex])) {
|
||||||
|
$transformer = $transformers[$transformerIndex];
|
||||||
|
$captureName = str_repeat($transformerIndex, $length);
|
||||||
|
|
||||||
|
return "(?P<$captureName>".$transformer->getReverseMatchingRegExp($length).')';
|
||||||
|
}
|
||||||
|
}, $escapedPattern);
|
||||||
|
|
||||||
|
return $reverseMatchingRegExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the first char of a string is a single quote
|
||||||
|
*
|
||||||
|
* @param string $quoteMatch The string to check
|
||||||
|
*
|
||||||
|
* @return Boolean true if matches, false otherwise
|
||||||
|
*/
|
||||||
|
public function isQuoteMatch($quoteMatch)
|
||||||
|
{
|
||||||
|
return ("'" === $quoteMatch[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces single quotes at the start or end of a string with two single quotes
|
||||||
|
*
|
||||||
|
* @param string $quoteMatch The string to replace the quotes
|
||||||
|
*
|
||||||
|
* @return string A string with the single quotes replaced
|
||||||
|
*/
|
||||||
|
public function replaceQuoteMatch($quoteMatch)
|
||||||
|
{
|
||||||
|
if (preg_match("/^'+$/", $quoteMatch)) {
|
||||||
|
return str_replace("''", "'", $quoteMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return str_replace("''", "'", substr($quoteMatch, 1, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a chars match regular expression
|
||||||
|
*
|
||||||
|
* @param string $specialChars A string of chars to build the regular expression
|
||||||
|
*
|
||||||
|
* @return string The chars match regular expression
|
||||||
|
*/
|
||||||
|
protected function buildCharsMatch($specialChars)
|
||||||
|
{
|
||||||
|
$specialCharsArray = str_split($specialChars);
|
||||||
|
|
||||||
|
$specialCharsMatch = implode('|', array_map(function($char) {
|
||||||
|
return $char.'+';
|
||||||
|
}, $specialCharsArray));
|
||||||
|
|
||||||
|
return $specialCharsMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a preg_replace match array, removing the numeric keys and returning an associative array
|
||||||
|
* with the value and pattern values for the matched Transformer
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function normalizeArray(array $data)
|
||||||
|
{
|
||||||
|
$ret = array();
|
||||||
|
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
if (!is_string($key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret[$key[0]] = array(
|
||||||
|
'value' => $value,
|
||||||
|
'pattern' => $key
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the Unix timestamp based on the matched values by the reverse matching regular
|
||||||
|
* expression of parse()
|
||||||
|
*
|
||||||
|
* @param \DateTime $dateTime The DateTime object to be used to calculate the timestamp
|
||||||
|
* @param array $options An array with the matched values to be used to calculate the timestamp
|
||||||
|
*
|
||||||
|
* @return Boolean|int The calculated timestamp or false if matched date is invalid
|
||||||
|
*/
|
||||||
|
protected function calculateUnixTimestamp(\DateTime $dateTime, array $options)
|
||||||
|
{
|
||||||
|
$options = $this->getDefaultValueForOptions($options);
|
||||||
|
|
||||||
|
$year = $options['year'];
|
||||||
|
$month = $options['month'];
|
||||||
|
$day = $options['day'];
|
||||||
|
$hour = $options['hour'];
|
||||||
|
$hourInstance = $options['hourInstance'];
|
||||||
|
$minute = $options['minute'];
|
||||||
|
$second = $options['second'];
|
||||||
|
$marker = $options['marker'];
|
||||||
|
$timezone = $options['timezone'];
|
||||||
|
|
||||||
|
// If month is false, return immediately (intl behavior)
|
||||||
|
if (false === $month) {
|
||||||
|
StubIntlGlobals::setError(StubIntlGlobals::U_PARSE_ERROR, 'Date parsing failed');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize hour
|
||||||
|
if ($hourInstance instanceof HourTransformer) {
|
||||||
|
$hour = $hourInstance->normalizeHour($hour, $marker);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the timezone if different from the default one
|
||||||
|
if (null !== $timezone && $timezone !== $this->timezone) {
|
||||||
|
$dateTime->setTimezone(new \DateTimeZone($timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize yy year
|
||||||
|
preg_match_all($this->regExp, $this->pattern, $matches);
|
||||||
|
if (in_array('yy', $matches[0])) {
|
||||||
|
$dateTime->setTimestamp(time());
|
||||||
|
$year = $year > $dateTime->format('y') + 20 ? 1900 + $year : 2000 + $year;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dateTime->setDate($year, $month, $day);
|
||||||
|
$dateTime->setTime($hour, $minute, $second);
|
||||||
|
|
||||||
|
return $dateTime->getTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add sensible default values for missing items in the extracted date/time options array. The values
|
||||||
|
* are base in the beginning of the Unix era
|
||||||
|
*
|
||||||
|
* @param array $options
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getDefaultValueForOptions(array $options)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'year' => isset($options['year']) ? $options['year'] : 1970,
|
||||||
|
'month' => isset($options['month']) ? $options['month'] : 1,
|
||||||
|
'day' => isset($options['day']) ? $options['day'] : 1,
|
||||||
|
'hour' => isset($options['hour']) ? $options['hour'] : 0,
|
||||||
|
'hourInstance' => isset($options['hourInstance']) ? $options['hourInstance'] : null,
|
||||||
|
'minute' => isset($options['minute']) ? $options['minute'] : 0,
|
||||||
|
'second' => isset($options['second']) ? $options['second'] : 0,
|
||||||
|
'marker' => isset($options['marker']) ? $options['marker'] : null,
|
||||||
|
'timezone' => isset($options['timezone']) ? $options['timezone'] : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for 12 hour format (0-11)
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class Hour1200Transformer extends HourTransformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
$hourOfDay = $dateTime->format('g');
|
||||||
|
$hourOfDay = '12' == $hourOfDay ? '0' : $hourOfDay;
|
||||||
|
|
||||||
|
return $this->padLeft($hourOfDay, $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function normalizeHour($hour, $marker = null)
|
||||||
|
{
|
||||||
|
if ('PM' === $marker) {
|
||||||
|
$hour += 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hour;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return '\d{1,2}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'hour' => (int) $matched,
|
||||||
|
'hourInstance' => $this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for 12 hour format (1-12)
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class Hour1201Transformer extends HourTransformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
return $this->padLeft($dateTime->format('g'), $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function normalizeHour($hour, $marker = null)
|
||||||
|
{
|
||||||
|
if ('PM' !== $marker && 12 === $hour) {
|
||||||
|
$hour = 0;
|
||||||
|
} elseif ('PM' === $marker && 12 !== $hour) {
|
||||||
|
// If PM and hour is not 12 (1-12), sum 12 hour
|
||||||
|
$hour += 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hour;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return '\d{1,2}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'hour' => (int) $matched,
|
||||||
|
'hourInstance' => $this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for 24 hour format (0-23)
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class Hour2400Transformer extends HourTransformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
return $this->padLeft($dateTime->format('G'), $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function normalizeHour($hour, $marker = null)
|
||||||
|
{
|
||||||
|
if ('AM' == $marker) {
|
||||||
|
$hour = 0;
|
||||||
|
} elseif ('PM' == $marker) {
|
||||||
|
$hour = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hour;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return '\d{1,2}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'hour' => (int) $matched,
|
||||||
|
'hourInstance' => $this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for 24 hour format (1-24)
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class Hour2401Transformer extends HourTransformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
$hourOfDay = $dateTime->format('G');
|
||||||
|
$hourOfDay = ('0' == $hourOfDay) ? '24' : $hourOfDay;
|
||||||
|
|
||||||
|
return $this->padLeft($hourOfDay, $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function normalizeHour($hour, $marker = null)
|
||||||
|
{
|
||||||
|
if ((null === $marker && 24 === $hour) || 'AM' == $marker) {
|
||||||
|
$hour = 0;
|
||||||
|
} elseif ('PM' == $marker) {
|
||||||
|
$hour = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hour;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return '\d{1,2}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'hour' => (int) $matched,
|
||||||
|
'hourInstance' => $this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for hour transformers
|
||||||
|
*
|
||||||
|
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
||||||
|
*/
|
||||||
|
abstract class HourTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a normalized hour value suitable for the hour transformer type
|
||||||
|
*
|
||||||
|
* @param int $hour The hour value
|
||||||
|
* @param string $marker An optional AM/PM marker
|
||||||
|
*
|
||||||
|
* @return int The normalized hour value
|
||||||
|
*/
|
||||||
|
abstract public function normalizeHour($hour, $marker = null);
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for minute format
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class MinuteTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
$minuteOfHour = (int) $dateTime->format('i');
|
||||||
|
|
||||||
|
return $this->padLeft($minuteOfHour, $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return 1 === $length ? '\d{1,2}' : '\d{'.$length.'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'minute' => (int) $matched,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,143 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for month format
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class MonthTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $months = array(
|
||||||
|
'January',
|
||||||
|
'February',
|
||||||
|
'March',
|
||||||
|
'April',
|
||||||
|
'May',
|
||||||
|
'June',
|
||||||
|
'July',
|
||||||
|
'August',
|
||||||
|
'September',
|
||||||
|
'October',
|
||||||
|
'November',
|
||||||
|
'December'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Short months names (first 3 letters)
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $shortMonths = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flipped $months array, $name => $index
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $flippedMonths = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flipped $shortMonths array, $name => $index
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $flippedShortMonths = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if (0 === count(self::$shortMonths)) {
|
||||||
|
self::$shortMonths = array_map(function($month) {
|
||||||
|
return substr($month, 0, 3);
|
||||||
|
}, self::$months);
|
||||||
|
|
||||||
|
self::$flippedMonths = array_flip(self::$months);
|
||||||
|
self::$flippedShortMonths = array_flip(self::$shortMonths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
$matchLengthMap = array(
|
||||||
|
1 => 'n',
|
||||||
|
2 => 'm',
|
||||||
|
3 => 'M',
|
||||||
|
4 => 'F',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($matchLengthMap[$length])) {
|
||||||
|
return $dateTime->format($matchLengthMap[$length]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (5 === $length) {
|
||||||
|
return substr($dateTime->format('M'), 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->padLeft($dateTime->format('m'), $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
switch ($length) {
|
||||||
|
case 1:
|
||||||
|
$regExp = '\d{1,2}';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
$regExp = implode('|', self::$shortMonths);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
$regExp = implode('|', self::$months);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
$regExp = '[JFMASOND]';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$regExp = '\d{'.$length.'}';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $regExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
if (!is_numeric($matched)) {
|
||||||
|
if (3 === $length) {
|
||||||
|
$matched = self::$flippedShortMonths[$matched] + 1;
|
||||||
|
} elseif (4 === $length) {
|
||||||
|
$matched = self::$flippedMonths[$matched] + 1;
|
||||||
|
} elseif (5 === $length) {
|
||||||
|
// IntlDateFormatter::parse() always returns false for MMMMM or LLLLL
|
||||||
|
$matched = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$matched = (int) $matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'month' => $matched,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for quarter format
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class QuarterTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
$month = (int) $dateTime->format('n');
|
||||||
|
$quarter = (int) floor(($month - 1) / 3) + 1;
|
||||||
|
switch ($length) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
return $this->padLeft($quarter, $length);
|
||||||
|
case 3:
|
||||||
|
return 'Q'.$quarter;
|
||||||
|
default:
|
||||||
|
$map = array(1 => '1st quarter', 2 => '2nd quarter', 3 => '3rd quarter', 4 => '4th quarter');
|
||||||
|
|
||||||
|
return $map[$quarter];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
switch ($length) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
return '\d{'.$length.'}';
|
||||||
|
case 3:
|
||||||
|
return 'Q\d';
|
||||||
|
default:
|
||||||
|
return '(?:1st|2nd|3rd|4th) quarter';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for the second format
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class SecondTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
$secondOfMinute = (int) $dateTime->format('s');
|
||||||
|
|
||||||
|
return $this->padLeft($secondOfMinute, $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return 1 === $length ? '\d{1,2}' : '\d{'.$length.'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'second' => (int) $matched,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\NotImplementedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for time zone format
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class TimeZoneTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws NotImplementedException When time zone is different than UTC or GMT (Etc/GMT)
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
$timeZone = substr($dateTime->getTimezone()->getName(), 0, 3);
|
||||||
|
|
||||||
|
if (!in_array($timeZone, array('Etc', 'UTC'))) {
|
||||||
|
throw new NotImplementedException('Time zone different than GMT or UTC is not supported as a formatting output.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// From ICU >= 4.8, the zero offset is not more used, example: GMT instead of GMT+00:00
|
||||||
|
$format = (0 !== (int) $dateTime->format('O')) ? '\G\M\TP' : '\G\M\T';
|
||||||
|
|
||||||
|
return $dateTime->format($format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return 'GMT[+-]\d{2}:?\d{2}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'timezone' => self::getEtcTimeZoneId($matched)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an Etc/GMT timezone identifier for the specified timezone
|
||||||
|
*
|
||||||
|
* The PHP documentation for timezones states to not use the 'Other' time zones because them exists
|
||||||
|
* "for backwards compatibility". However all Etc/GMT time zones are in the tz database 'etcetera' file,
|
||||||
|
* which indicates they are not deprecated (neither are old names).
|
||||||
|
*
|
||||||
|
* Only GMT, Etc/Universal, Etc/Zulu, Etc/Greenwich, Etc/GMT-0, Etc/GMT+0 and Etc/GMT0 are old names and
|
||||||
|
* are linked to Etc/GMT or Etc/UTC.
|
||||||
|
*
|
||||||
|
* @param string $formattedTimeZone A GMT timezone string (GMT-03:00, e.g.)
|
||||||
|
*
|
||||||
|
* @return string A timezone identifier
|
||||||
|
*
|
||||||
|
* @see http://php.net/manual/en/timezones.others.php
|
||||||
|
* @see http://www.twinsun.com/tz/tz-link.htm
|
||||||
|
*
|
||||||
|
* @throws NotImplementedException When the GMT time zone have minutes offset different than zero
|
||||||
|
* @throws \InvalidArgumentException When the value can not be matched with pattern
|
||||||
|
*/
|
||||||
|
public static function getEtcTimeZoneId($formattedTimeZone)
|
||||||
|
{
|
||||||
|
if (preg_match('/GMT(?P<signal>[+-])(?P<hours>\d{2}):?(?P<minutes>\d{2})/', $formattedTimeZone, $matches)) {
|
||||||
|
$hours = (int) $matches['hours'];
|
||||||
|
$minutes = (int) $matches['minutes'];
|
||||||
|
$signal = $matches['signal'] == '-' ? '+' : '-';
|
||||||
|
|
||||||
|
if (0 < $minutes) {
|
||||||
|
throw new NotImplementedException(sprintf(
|
||||||
|
'It is not possible to use a GMT time zone with minutes offset different than zero (0). GMT time zone tried: %s.',
|
||||||
|
$formattedTimeZone
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Etc/GMT'.($hours !== 0 ? $signal.$hours : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \InvalidArgumentException('The GMT time zone \'%s\' does not match with the supported formats GMT[+-]HH:MM or GMT[+-]HHMM.');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for date formats
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
abstract class Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Format a value using a configured DateTime as date/time source
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param \DateTime $dateTime A DateTime object to be used to generate the formatted value
|
||||||
|
* @param int $length The formatted value string length
|
||||||
|
*
|
||||||
|
* @return string The formatted value
|
||||||
|
*/
|
||||||
|
abstract public function format(\DateTime $dateTime, $length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reverse matching regular expression of a string generated by format()
|
||||||
|
*
|
||||||
|
* @param int $length The length of the value to be reverse matched
|
||||||
|
*
|
||||||
|
* @return string The reverse matching regular expression
|
||||||
|
*/
|
||||||
|
abstract public function getReverseMatchingRegExp($length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract date options from a matched value returned by the processing of the reverse matching
|
||||||
|
* regular expression
|
||||||
|
*
|
||||||
|
* @param string $matched The matched value
|
||||||
|
* @param int $length The length of the Transformer pattern string
|
||||||
|
*
|
||||||
|
* @return array An associative array
|
||||||
|
*/
|
||||||
|
abstract public function extractDateOptions($matched, $length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pad a string with zeros to the left
|
||||||
|
*
|
||||||
|
* @param string $value The string to be padded
|
||||||
|
* @param int $length The length to pad
|
||||||
|
*
|
||||||
|
* @return string The padded string
|
||||||
|
*/
|
||||||
|
protected function padLeft($value, $length)
|
||||||
|
{
|
||||||
|
return str_pad($value, $length, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser and formatter for year format
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class YearTransformer extends Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(\DateTime $dateTime, $length)
|
||||||
|
{
|
||||||
|
if (2 === $length) {
|
||||||
|
return $dateTime->format('y');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->padLeft($dateTime->format('Y'), $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getReverseMatchingRegExp($length)
|
||||||
|
{
|
||||||
|
return 2 === $length ? '\d{2}' : '\d{4}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function extractDateOptions($matched, $length)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'year' => (int) $matched,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,601 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\DateFormatter;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Globals\StubIntlGlobals;
|
||||||
|
use Symfony\Component\Intl\DateFormatter\DateFormat\FullTransformer;
|
||||||
|
use Symfony\Component\Intl\Exception\MethodNotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Locale\StubLocale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a stub IntlDateFormatter for the 'en' locale.
|
||||||
|
*
|
||||||
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*/
|
||||||
|
class StubIntlDateFormatter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The error code from the last operation
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
protected $errorCode = StubIntlGlobals::U_ZERO_ERROR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The error message from the last operation
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $errorMessage = 'U_ZERO_ERROR';
|
||||||
|
|
||||||
|
/* date/time format types */
|
||||||
|
const NONE = -1;
|
||||||
|
const FULL = 0;
|
||||||
|
const LONG = 1;
|
||||||
|
const MEDIUM = 2;
|
||||||
|
const SHORT = 3;
|
||||||
|
|
||||||
|
/* calendar formats */
|
||||||
|
const TRADITIONAL = 0;
|
||||||
|
const GREGORIAN = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Patterns used to format the date when no pattern is provided
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $defaultDateFormats = array(
|
||||||
|
self::NONE => '',
|
||||||
|
self::FULL => 'EEEE, LLLL d, y',
|
||||||
|
self::LONG => 'LLLL d, y',
|
||||||
|
self::MEDIUM => 'LLL d, y',
|
||||||
|
self::SHORT => 'M/d/yy',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Patterns used to format the time when no pattern is provided
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $defaultTimeFormats = array(
|
||||||
|
self::FULL => 'h:mm:ss a zzzz',
|
||||||
|
self::LONG => 'h:mm:ss a z',
|
||||||
|
self::MEDIUM => 'h:mm:ss a',
|
||||||
|
self::SHORT => 'h:mm a',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $datetype;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $timetype;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \DateTimeZone
|
||||||
|
*/
|
||||||
|
private $dateTimeZone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Boolean
|
||||||
|
*/
|
||||||
|
private $unitializedTimeZoneId = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $timeZoneId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code
|
||||||
|
* @param int $datetype Type of date formatting, one of the format type constants
|
||||||
|
* @param int $timetype Type of time formatting, one of the format type constants
|
||||||
|
* @param string $timezone Timezone identifier
|
||||||
|
* @param int $calendar Calendar to use for formatting or parsing; default is Gregorian.
|
||||||
|
* One of the calendar constants.
|
||||||
|
* @param string $pattern Optional pattern to use when formatting
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.create.php
|
||||||
|
* @see http://userguide.icu-project.org/formatparse/datetime
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When $locale different than 'en' is passed
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When $calendar different than GREGORIAN is passed
|
||||||
|
*/
|
||||||
|
public function __construct($locale, $datetype, $timetype, $timezone = null, $calendar = self::GREGORIAN, $pattern = null)
|
||||||
|
{
|
||||||
|
if ('en' !== $locale) {
|
||||||
|
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'locale', $locale, 'Only the \'en\' locale is supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::GREGORIAN !== $calendar) {
|
||||||
|
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'calendar', $calendar, 'Only the GREGORIAN calendar is supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->datetype = $datetype;
|
||||||
|
$this->timetype = $timetype;
|
||||||
|
|
||||||
|
$this->setPattern($pattern);
|
||||||
|
$this->setTimeZoneId($timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static constructor
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code
|
||||||
|
* @param int $datetype Type of date formatting, one of the format type constants
|
||||||
|
* @param int $timetype Type of time formatting, one of the format type constants
|
||||||
|
* @param string $timezone Timezone identifier
|
||||||
|
* @param int $calendar Calendar to use for formatting or parsing; default is Gregorian.
|
||||||
|
* One of the calendar constants.
|
||||||
|
* @param string $pattern Optional pattern to use when formatting
|
||||||
|
*
|
||||||
|
* @return StubIntlDateFormatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.create.php
|
||||||
|
* @see http://userguide.icu-project.org/formatparse/datetime
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When $locale different than 'en' is passed
|
||||||
|
*/
|
||||||
|
public static function create($locale, $datetype, $timetype, $timezone = null, $calendar = self::GREGORIAN, $pattern = null)
|
||||||
|
{
|
||||||
|
return new self($locale, $datetype, $timetype, $timezone, $calendar, $pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the date/time value (timestamp) as a string
|
||||||
|
*
|
||||||
|
* @param mixed $timestamp Unix timestamp to format
|
||||||
|
*
|
||||||
|
* @return string The formatted value
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.format.php
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentValueNotImplementedException If one of the formatting characters is not implemented
|
||||||
|
*/
|
||||||
|
public function format($timestamp)
|
||||||
|
{
|
||||||
|
// intl allows timestamps to be passed as arrays - we don't
|
||||||
|
if (is_array($timestamp)) {
|
||||||
|
$message = version_compare(PHP_VERSION, '5.3.4', '>=') ?
|
||||||
|
'Only integer unix timestamps and DateTime objects are supported' :
|
||||||
|
'Only integer unix timestamps are supported';
|
||||||
|
|
||||||
|
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'timestamp', $timestamp, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// behave like the intl extension
|
||||||
|
$argumentError = null;
|
||||||
|
if (version_compare(PHP_VERSION, '5.3.4', '<') && !is_int($timestamp)) {
|
||||||
|
$argumentError = 'datefmt_format: takes either an array or an integer timestamp value ';
|
||||||
|
} elseif (version_compare(PHP_VERSION, '5.3.4', '>=') && !is_int($timestamp) && !$timestamp instanceof \DateTime) {
|
||||||
|
$argumentError = 'datefmt_format: takes either an array or an integer timestamp value or a DateTime object';
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=') && !is_int($timestamp)) {
|
||||||
|
$argumentError = sprintf('datefmt_format: string \'%s\' is not numeric, which would be required for it to be a valid date', $timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $argumentError) {
|
||||||
|
StubIntlGlobals::setError(StubIntlGlobals::U_ILLEGAL_ARGUMENT_ERROR, $argumentError);
|
||||||
|
$this->errorCode = StubIntlGlobals::getErrorCode();
|
||||||
|
$this->errorMessage = StubIntlGlobals::getErrorMessage();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// As of PHP 5.3.4, IntlDateFormatter::format() accepts DateTime instances
|
||||||
|
if (version_compare(PHP_VERSION, '5.3.4', '>=') && $timestamp instanceof \DateTime) {
|
||||||
|
$timestamp = $timestamp->getTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
$transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId());
|
||||||
|
$formatted = $transformer->format($this->createDateTime($timestamp));
|
||||||
|
|
||||||
|
// behave like the intl extension
|
||||||
|
StubIntlGlobals::setError(StubIntlGlobals::U_ZERO_ERROR);
|
||||||
|
$this->errorCode = StubIntlGlobals::getErrorCode();
|
||||||
|
$this->errorMessage = StubIntlGlobals::getErrorMessage();
|
||||||
|
|
||||||
|
return $formatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats an object
|
||||||
|
*
|
||||||
|
* @param object $object
|
||||||
|
* @param mixed $format
|
||||||
|
* @param string $locale
|
||||||
|
*
|
||||||
|
* @return string The formatted value
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.formatobject.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function formatObject($object, $format = null, $locale = null)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatter's calendar
|
||||||
|
*
|
||||||
|
* @return int The calendar being used by the formatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.getcalendar.php
|
||||||
|
*/
|
||||||
|
public function getCalendar()
|
||||||
|
{
|
||||||
|
return self::GREGORIAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatter's calendar object
|
||||||
|
*
|
||||||
|
* @return object The calendar's object being used by the formatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.getcalendarobject.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function getCalendarObject()
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatter's datetype
|
||||||
|
*
|
||||||
|
* @return int The current value of the formatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.getdatetype.php
|
||||||
|
*/
|
||||||
|
public function getDateType()
|
||||||
|
{
|
||||||
|
return $this->datetype;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns formatter's last error code. Always returns the U_ZERO_ERROR class constant value
|
||||||
|
*
|
||||||
|
* @return int The error code from last formatter call
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.geterrorcode.php
|
||||||
|
*/
|
||||||
|
public function getErrorCode()
|
||||||
|
{
|
||||||
|
return $this->errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns formatter's last error message. Always returns the U_ZERO_ERROR_MESSAGE class constant value
|
||||||
|
*
|
||||||
|
* @return string The error message from last formatter call
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.geterrormessage.php
|
||||||
|
*/
|
||||||
|
public function getErrorMessage()
|
||||||
|
{
|
||||||
|
return $this->errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatter's locale
|
||||||
|
*
|
||||||
|
* @param int $type The locale name type to return between valid or actual (StubLocale::VALID_LOCALE or StubLocale::ACTUAL_LOCALE, respectively)
|
||||||
|
*
|
||||||
|
* @return string The locale name used to create the formatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.getlocale.php
|
||||||
|
*/
|
||||||
|
public function getLocale($type = StubLocale::ACTUAL_LOCALE)
|
||||||
|
{
|
||||||
|
return 'en';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatter's pattern
|
||||||
|
*
|
||||||
|
* @return string The pattern string used by the formatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.getpattern.php
|
||||||
|
*/
|
||||||
|
public function getPattern()
|
||||||
|
{
|
||||||
|
return $this->pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatter's time type
|
||||||
|
*
|
||||||
|
* @return string The time type used by the formatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.gettimetype.php
|
||||||
|
*/
|
||||||
|
public function getTimeType()
|
||||||
|
{
|
||||||
|
return $this->timetype;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatter's timezone identifier
|
||||||
|
*
|
||||||
|
* @return string The timezone identifier used by the formatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.gettimezoneid.php
|
||||||
|
*/
|
||||||
|
public function getTimeZoneId()
|
||||||
|
{
|
||||||
|
if (!$this->unitializedTimeZoneId) {
|
||||||
|
return $this->timeZoneId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In PHP 5.5 default timezone depends on `date_default_timezone_get()` method
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
return date_default_timezone_get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatter's timezone
|
||||||
|
*
|
||||||
|
* @return mixed The timezone used by the formatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.gettimezone.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function getTimeZone()
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the formatter is lenient
|
||||||
|
*
|
||||||
|
* @return Boolean
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.islenient.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function isLenient()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse string to a field-based time value
|
||||||
|
*
|
||||||
|
* @param string $value String to convert to a time value
|
||||||
|
* @param int $position Position at which to start the parsing in $value (zero-based).
|
||||||
|
* If no error occurs before $value is consumed, $parse_pos will
|
||||||
|
* contain -1 otherwise it will contain the position at which parsing
|
||||||
|
* ended. If $parse_pos > strlen($value), the parse fails immediately.
|
||||||
|
*
|
||||||
|
* @return string Localtime compatible array of integers: contains 24 hour clock value in tm_hour field
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.localtime.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function localtime($value, &$position = 0)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse string to a timestamp value
|
||||||
|
*
|
||||||
|
* @param string $value String to convert to a time value
|
||||||
|
* @param int $position Position at which to start the parsing in $value (zero-based).
|
||||||
|
* If no error occurs before $value is consumed, $parse_pos will
|
||||||
|
* contain -1 otherwise it will contain the position at which parsing
|
||||||
|
* ended. If $parse_pos > strlen($value), the parse fails immediately.
|
||||||
|
*
|
||||||
|
* @return string Parsed value as a timestamp
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.parse.php
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentNotImplementedException When $position different than null, behavior not implemented
|
||||||
|
*/
|
||||||
|
public function parse($value, &$position = null)
|
||||||
|
{
|
||||||
|
// We don't calculate the position when parsing the value
|
||||||
|
if (null !== $position) {
|
||||||
|
throw new MethodArgumentNotImplementedException(__METHOD__, 'position');
|
||||||
|
}
|
||||||
|
|
||||||
|
$dateTime = $this->createDateTime(0);
|
||||||
|
$transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId());
|
||||||
|
|
||||||
|
$timestamp = $transformer->parse($dateTime, $value);
|
||||||
|
|
||||||
|
// behave like the intl extension. FullTransformer::parse() set the proper error
|
||||||
|
$this->errorCode = StubIntlGlobals::getErrorCode();
|
||||||
|
$this->errorMessage = StubIntlGlobals::getErrorMessage();
|
||||||
|
|
||||||
|
return $timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the formatter's calendar
|
||||||
|
*
|
||||||
|
* @param string $calendar The calendar to use. Default is IntlDateFormatter::GREGORIAN.
|
||||||
|
*
|
||||||
|
* @return Boolean true on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.setcalendar.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function setCalendar($calendar)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the leniency of the parser
|
||||||
|
*
|
||||||
|
* Define if the parser is strict or lenient in interpreting inputs that do not match the pattern
|
||||||
|
* exactly. Enabling lenient parsing allows the parser to accept otherwise flawed date or time
|
||||||
|
* patterns, parsing as much as possible to obtain a value. Extra space, unrecognized tokens, or
|
||||||
|
* invalid values ("February 30th") are not accepted.
|
||||||
|
*
|
||||||
|
* @param Boolean $lenient Sets whether the parser is lenient or not, default is false (strict)
|
||||||
|
*
|
||||||
|
* @return Boolean true on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.setlenient.php
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When $lenient is true
|
||||||
|
*/
|
||||||
|
public function setLenient($lenient)
|
||||||
|
{
|
||||||
|
if ($lenient) {
|
||||||
|
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'lenient', $lenient, 'Only the strict parser is supported');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the formatter's pattern
|
||||||
|
*
|
||||||
|
* @param string $pattern A pattern string in conformance with the ICU IntlDateFormatter documentation
|
||||||
|
*
|
||||||
|
* @return Boolean true on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.setpattern.php
|
||||||
|
* @see http://userguide.icu-project.org/formatparse/datetime
|
||||||
|
*/
|
||||||
|
public function setPattern($pattern)
|
||||||
|
{
|
||||||
|
if (null === $pattern) {
|
||||||
|
$pattern = $this->getDefaultPattern();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pattern = $pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the formatter's timezone identifier
|
||||||
|
*
|
||||||
|
* @param string $timeZoneId The time zone ID string of the time zone to use.
|
||||||
|
* If NULL or the empty string, the default time zone for the
|
||||||
|
* runtime is used.
|
||||||
|
*
|
||||||
|
* @return Boolean true on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.settimezoneid.php
|
||||||
|
*/
|
||||||
|
public function setTimeZoneId($timeZoneId)
|
||||||
|
{
|
||||||
|
if (null === $timeZoneId) {
|
||||||
|
// In PHP 5.5 if $timeZoneId is null it fallbacks to `date_default_timezone_get()` method
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
$timeZoneId = date_default_timezone_get();
|
||||||
|
} else {
|
||||||
|
// TODO: changes were made to ext/intl in PHP 5.4.4 release that need to be investigated since it will
|
||||||
|
// use ini's date.timezone when the time zone is not provided. As a not well tested workaround, uses UTC.
|
||||||
|
// See the first two items of the commit message for more information:
|
||||||
|
// https://github.com/php/php-src/commit/eb346ef0f419b90739aadfb6cc7b7436c5b521d9
|
||||||
|
$timeZoneId = getenv('TZ') ?: 'UTC';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->unitializedTimeZoneId = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backup original passed time zone
|
||||||
|
$timeZone = $timeZoneId;
|
||||||
|
|
||||||
|
// Get an Etc/GMT time zone that is accepted for \DateTimeZone
|
||||||
|
if ('GMT' !== $timeZoneId && 0 === strpos($timeZoneId, 'GMT')) {
|
||||||
|
try {
|
||||||
|
$timeZoneId = DateFormat\TimeZoneTransformer::getEtcTimeZoneId($timeZoneId);
|
||||||
|
} catch (\InvalidArgumentException $e) {
|
||||||
|
// Does nothing, will fallback to UTC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->dateTimeZone = new \DateTimeZone($timeZoneId);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->dateTimeZone = new \DateTimeZone('UTC');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->timeZoneId = $timeZone;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method was added in PHP 5.5 as replacement for `setTimeZoneId()`
|
||||||
|
*
|
||||||
|
* @param mixed $timeZone
|
||||||
|
*
|
||||||
|
* @return Boolean true on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/intldateformatter.settimezone.php
|
||||||
|
*/
|
||||||
|
public function setTimeZone($timeZone)
|
||||||
|
{
|
||||||
|
return $this->setTimeZoneId($timeZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and returns a DateTime object with the specified timestamp and with the
|
||||||
|
* current time zone
|
||||||
|
*
|
||||||
|
* @param int $timestamp
|
||||||
|
*
|
||||||
|
* @return \DateTime
|
||||||
|
*/
|
||||||
|
protected function createDateTime($timestamp)
|
||||||
|
{
|
||||||
|
$dateTime = new \DateTime();
|
||||||
|
$dateTime->setTimestamp($timestamp);
|
||||||
|
$dateTime->setTimezone($this->dateTimeZone);
|
||||||
|
|
||||||
|
return $dateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pattern string based in the datetype and timetype values
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getDefaultPattern()
|
||||||
|
{
|
||||||
|
$patternParts = array();
|
||||||
|
if (self::NONE !== $this->datetype) {
|
||||||
|
$patternParts[] = $this->defaultDateFormats[$this->datetype];
|
||||||
|
}
|
||||||
|
if (self::NONE !== $this->timetype) {
|
||||||
|
$patternParts[] = $this->defaultTimeFormats[$this->timetype];
|
||||||
|
}
|
||||||
|
$pattern = implode(' ', $patternParts);
|
||||||
|
|
||||||
|
return $pattern;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base BadMethodCallException for the Intl component.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
|
||||||
|
{
|
||||||
|
}
|
21
src/Symfony/Component/Intl/Exception/ExceptionInterface.php
Normal file
21
src/Symfony/Component/Intl/Exception/ExceptionInterface.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base ExceptionInterface for the Intl component.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface ExceptionInterface
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InvalidArgumentException for the Intl component.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Exception;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\NotImplementedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
||||||
|
*/
|
||||||
|
class MethodArgumentNotImplementedException extends NotImplementedException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $methodName The method name that raised the exception
|
||||||
|
* @param string $argName The argument name that is not implemented
|
||||||
|
*/
|
||||||
|
public function __construct($methodName, $argName)
|
||||||
|
{
|
||||||
|
$message = sprintf('The %s() method\'s argument $%s behavior is not implemented.', $methodName, $argName);
|
||||||
|
parent::__construct($message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Exception;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\NotImplementedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
||||||
|
*/
|
||||||
|
class MethodArgumentValueNotImplementedException extends NotImplementedException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $methodName The method name that raised the exception
|
||||||
|
* @param string $argName The argument name
|
||||||
|
* @param string $argValue The argument value that is not implemented
|
||||||
|
* @param string $additionalMessage An optional additional message to append to the exception message
|
||||||
|
*/
|
||||||
|
public function __construct($methodName, $argName, $argValue, $additionalMessage = '')
|
||||||
|
{
|
||||||
|
$message = sprintf(
|
||||||
|
'The %s() method\'s argument $%s value %s behavior is not implemented.%s',
|
||||||
|
$methodName,
|
||||||
|
$argName,
|
||||||
|
var_export($argValue, true),
|
||||||
|
$additionalMessage !== '' ? ' '.$additionalMessage.'. ' : ''
|
||||||
|
);
|
||||||
|
|
||||||
|
parent::__construct($message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
||||||
|
*/
|
||||||
|
class MethodNotImplementedException extends NotImplementedException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $methodName The name of the method
|
||||||
|
*/
|
||||||
|
public function __construct($methodName)
|
||||||
|
{
|
||||||
|
parent::__construct(sprintf('The %s() is not implemented.', $methodName));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base exception class for not implemented behaviors of the intl extension in the Locale component.
|
||||||
|
*
|
||||||
|
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
||||||
|
*/
|
||||||
|
class NotImplementedException extends RuntimeException
|
||||||
|
{
|
||||||
|
const INTL_INSTALL_MESSAGE = 'Please install the "intl" extension for full localization capabilities.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $message The exception message. A note to install the intl extension is appended to this string
|
||||||
|
*/
|
||||||
|
public function __construct($message)
|
||||||
|
{
|
||||||
|
parent::__construct($message.' '.self::INTL_INSTALL_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base OutOfBoundsException for the Intl component.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
|
||||||
|
{
|
||||||
|
}
|
21
src/Symfony/Component/Intl/Exception/RuntimeException.php
Normal file
21
src/Symfony/Component/Intl/Exception/RuntimeException.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RuntimeException for the Intl component.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||||
|
{
|
||||||
|
}
|
137
src/Symfony/Component/Intl/Globals/StubIntlGlobals.php
Normal file
137
src/Symfony/Component/Intl/Globals/StubIntlGlobals.php
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Globals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides fake static versions of the global functions in the intl extension
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
abstract class StubIntlGlobals
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Indicates that no error occurred
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
const U_ZERO_ERROR = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that an invalid argument was passed
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
const U_ILLEGAL_ARGUMENT_ERROR = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the parse() operation failed
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
const U_PARSE_ERROR = 9;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All known error codes
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $errorCodes = array(
|
||||||
|
self::U_ZERO_ERROR => 'U_ZERO_ERROR',
|
||||||
|
self::U_ILLEGAL_ARGUMENT_ERROR => 'U_ILLEGAL_ARGUMENT_ERROR',
|
||||||
|
self::U_PARSE_ERROR => 'U_PARSE_ERROR',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The error code of the last operation
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
private static $errorCode = self::U_ZERO_ERROR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The error code of the last operation
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
private static $errorMessage = 'U_ZERO_ERROR';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the error code indicates a failure
|
||||||
|
*
|
||||||
|
* @param integer $errorCode The error code returned by StubIntlGlobals::getErrorCode()
|
||||||
|
*
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public static function isFailure($errorCode)
|
||||||
|
{
|
||||||
|
return isset(self::$errorCodes[$errorCode])
|
||||||
|
&& $errorCode > self::U_ZERO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the error code of the last operation
|
||||||
|
*
|
||||||
|
* Returns StubIntlGlobals::U_ZERO_ERROR if no error occurred.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public static function getErrorCode()
|
||||||
|
{
|
||||||
|
return self::$errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the error message of the last operation
|
||||||
|
*
|
||||||
|
* Returns "U_ZERO_ERROR" if no error occurred.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getErrorMessage()
|
||||||
|
{
|
||||||
|
return self::$errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the symbolic name for a given error code
|
||||||
|
*
|
||||||
|
* @param integer $code The error code returned by StubIntlGlobals::getErrorCode()
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getErrorName($code)
|
||||||
|
{
|
||||||
|
if (isset(self::$errorCodes[$code])) {
|
||||||
|
return self::$errorCodes[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
return '[BOGUS UErrorCode]';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current error
|
||||||
|
*
|
||||||
|
* @param integer $code One of the error constants in this class
|
||||||
|
* @param string $message The ICU class error message
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException If the code is not one of the error constants in this class
|
||||||
|
*/
|
||||||
|
public static function setError($code, $message = '')
|
||||||
|
{
|
||||||
|
if (!isset(self::$errorCodes[$code])) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('No such error code: "%s"', $code));
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$errorMessage = $message ? sprintf('%s: %s', $message, self::$errorCodes[$code]) : self::$errorCodes[$code];
|
||||||
|
self::$errorCode = $code;
|
||||||
|
}
|
||||||
|
}
|
332
src/Symfony/Component/Intl/Intl.php
Normal file
332
src/Symfony/Component/Intl/Intl.php
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl;
|
||||||
|
|
||||||
|
use Symfony\Component\Icu\IcuCurrencyBundle;
|
||||||
|
use Symfony\Component\Icu\IcuData;
|
||||||
|
use Symfony\Component\Icu\IcuLanguageBundle;
|
||||||
|
use Symfony\Component\Icu\IcuLocaleBundle;
|
||||||
|
use Symfony\Component\Icu\IcuRegionBundle;
|
||||||
|
use Symfony\Component\Intl\Exception\InvalidArgumentException;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Reader\BinaryBundleReader;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Reader\BufferedReader;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Reader\PhpBundleReader;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Reader\StructuredBundleReader;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Stub\StubCurrencyBundle;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Stub\StubLanguageBundle;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Stub\StubLocaleBundle;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Stub\StubRegionBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives access to internationalization data.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class Intl
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Load data from the Icu component.
|
||||||
|
*/
|
||||||
|
const ICU = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load data from the stub files of the Intl component.
|
||||||
|
*/
|
||||||
|
const STUB = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of resource bundles to buffer. Loading the same resource
|
||||||
|
* bundle for n locales takes up n spots in the buffer.
|
||||||
|
*/
|
||||||
|
const BUFFER_SIZE = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The accepted values for the {@link $dataSource} property.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $allowedDataSources = array(
|
||||||
|
self::ICU => 'Intl::ICU',
|
||||||
|
self::STUB => 'Intl::STUB',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
private static $dataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ResourceBundle\CurrencyBundleInterface
|
||||||
|
*/
|
||||||
|
private static $currencyBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ResourceBundle\LanguageBundleInterface
|
||||||
|
*/
|
||||||
|
private static $languageBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ResourceBundle\LocaleBundleInterface
|
||||||
|
*/
|
||||||
|
private static $localeBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ResourceBundle\RegionBundleInterface
|
||||||
|
*/
|
||||||
|
private static $regionBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|Boolean|null
|
||||||
|
*/
|
||||||
|
private static $icuVersion = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $icuDataVersion = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ResourceBundle\Reader\StructuredBundleReaderInterface
|
||||||
|
*/
|
||||||
|
private static $phpReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ResourceBundle\Reader\StructuredBundleReaderInterface
|
||||||
|
*/
|
||||||
|
private static $binaryReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the intl extension is installed.
|
||||||
|
*
|
||||||
|
* @return Boolean Returns true if the intl extension is installed, false otherwise.
|
||||||
|
*/
|
||||||
|
public static function isExtensionLoaded()
|
||||||
|
{
|
||||||
|
return IcuData::isLoadable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the data source from which to load the resource bundles.
|
||||||
|
*
|
||||||
|
* @param integer $dataSource One of the constants {@link Intl::ICU} or
|
||||||
|
* {@link Intl::STUB}.
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If the data source is invalid.
|
||||||
|
*
|
||||||
|
* @see getData>Source
|
||||||
|
*/
|
||||||
|
public static function setDataSource($dataSource)
|
||||||
|
{
|
||||||
|
if (!isset(self::$allowedDataSources[$dataSource])) {
|
||||||
|
throw new InvalidArgumentException(sprintf(
|
||||||
|
'The data sources should be one of %s',
|
||||||
|
implode(', ', self::$allowedDataSources)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::ICU === $dataSource && !IcuData::isLoadable()) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
'The data source cannot be set to Intl::ICU if the intl ' .
|
||||||
|
'extension is not installed.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dataSource !== self::$dataSource) {
|
||||||
|
self::$currencyBundle = null;
|
||||||
|
self::$languageBundle = null;
|
||||||
|
self::$localeBundle = null;
|
||||||
|
self::$regionBundle = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$dataSource = $dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data source from which to load the resource bundles.
|
||||||
|
*
|
||||||
|
* If {@link setDataSource()} has not been called, the data source will be
|
||||||
|
* chosen depending on whether the intl extension is installed or not:
|
||||||
|
*
|
||||||
|
* * If the extension is present, the bundles will be loaded from the Icu
|
||||||
|
* component;
|
||||||
|
* * Otherwise, the bundles will be loaded from the stub files in the
|
||||||
|
* Intl component.
|
||||||
|
*
|
||||||
|
* @return integer One of the constants {@link Intl::ICU} or
|
||||||
|
* {@link Intl::STUB}.
|
||||||
|
*/
|
||||||
|
public static function getDataSource()
|
||||||
|
{
|
||||||
|
if (null === self::$dataSource) {
|
||||||
|
self::$dataSource = IcuData::isLoadable() ? self::ICU : self::STUB;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bundle containing currency information.
|
||||||
|
*
|
||||||
|
* @return ResourceBundle\CurrencyBundleInterface The currency resource bundle.
|
||||||
|
*/
|
||||||
|
public static function getCurrencyBundle()
|
||||||
|
{
|
||||||
|
if (null === self::$currencyBundle) {
|
||||||
|
self::$currencyBundle = self::ICU === self::getDataSource()
|
||||||
|
? new IcuCurrencyBundle(self::getBinaryReader())
|
||||||
|
: new StubCurrencyBundle(self::getPhpReader());
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$currencyBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bundle containing language information.
|
||||||
|
*
|
||||||
|
* @return ResourceBundle\LanguageBundleInterface The language resource bundle.
|
||||||
|
*/
|
||||||
|
public static function getLanguageBundle()
|
||||||
|
{
|
||||||
|
if (null === self::$languageBundle) {
|
||||||
|
self::$languageBundle = self::ICU === self::getDataSource()
|
||||||
|
? new IcuLanguageBundle(self::getBinaryReader())
|
||||||
|
: new StubLanguageBundle(self::getPhpReader());
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$languageBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bundle containing locale information.
|
||||||
|
*
|
||||||
|
* @return ResourceBundle\LocaleBundleInterface The locale resource bundle.
|
||||||
|
*/
|
||||||
|
public static function getLocaleBundle()
|
||||||
|
{
|
||||||
|
if (null === self::$localeBundle) {
|
||||||
|
self::$localeBundle = self::ICU === self::getDataSource()
|
||||||
|
? new IcuLocaleBundle(self::getBinaryReader())
|
||||||
|
: new StubLocaleBundle(self::getPhpReader());
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$localeBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bundle containing region information.
|
||||||
|
*
|
||||||
|
* @return ResourceBundle\RegionBundleInterface The region resource bundle.
|
||||||
|
*/
|
||||||
|
public static function getRegionBundle()
|
||||||
|
{
|
||||||
|
if (null === self::$regionBundle) {
|
||||||
|
self::$regionBundle = self::ICU === self::getDataSource()
|
||||||
|
? new IcuRegionBundle(self::getBinaryReader())
|
||||||
|
: new StubRegionBundle(self::getPhpReader());
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$regionBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the version of the installed ICU library.
|
||||||
|
*
|
||||||
|
* @return null|string The ICU version or NULL if it could not be determined.
|
||||||
|
*/
|
||||||
|
public static function getIcuVersion()
|
||||||
|
{
|
||||||
|
if (false === self::$icuVersion) {
|
||||||
|
if (defined('INTL_ICU_VERSION')) {
|
||||||
|
self::$icuVersion = INTL_ICU_VERSION;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$reflector = new \ReflectionExtension('intl');
|
||||||
|
ob_start();
|
||||||
|
$reflector->info();
|
||||||
|
$output = strip_tags(ob_get_clean());
|
||||||
|
preg_match('/^ICU version (?:=>)?(.*)$/m', $output, $matches);
|
||||||
|
|
||||||
|
self::$icuVersion = trim($matches[1]);
|
||||||
|
} catch (\ReflectionException $e) {
|
||||||
|
self::$icuVersion = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$icuVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the version of the installed ICU data.
|
||||||
|
*
|
||||||
|
* @return string The version of the installed ICU data.
|
||||||
|
*/
|
||||||
|
public static function getIcuDataVersion()
|
||||||
|
{
|
||||||
|
if (false === self::$icuDataVersion) {
|
||||||
|
self::$icuDataVersion = self::ICU === self::getDataSource()
|
||||||
|
? IcuData::getVersion()
|
||||||
|
: file_get_contents(__DIR__ . '/Resources/version.txt');
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$icuDataVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ICU version that the stub classes mimic.
|
||||||
|
*
|
||||||
|
* @return string The ICU version of the stub classes.
|
||||||
|
*/
|
||||||
|
public static function getStubIcuVersion()
|
||||||
|
{
|
||||||
|
return '50.1.0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a resource bundle reader for .php resource bundle files.
|
||||||
|
*
|
||||||
|
* @return ResourceBundle\Reader\StructuredBundleReaderInterface The resource reader.
|
||||||
|
*/
|
||||||
|
private static function getPhpReader()
|
||||||
|
{
|
||||||
|
if (null === self::$phpReader) {
|
||||||
|
self::$phpReader = new StructuredBundleReader(new BufferedReader(
|
||||||
|
new PhpBundleReader(),
|
||||||
|
self::BUFFER_SIZE
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$phpReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a resource bundle reader for binary .res resource bundle files.
|
||||||
|
*
|
||||||
|
* @return ResourceBundle\Reader\StructuredBundleReaderInterface The resource reader.
|
||||||
|
*/
|
||||||
|
private static function getBinaryReader()
|
||||||
|
{
|
||||||
|
if (null === self::$binaryReader) {
|
||||||
|
self::$binaryReader = new StructuredBundleReader(new BufferedReader(
|
||||||
|
new BinaryBundleReader(),
|
||||||
|
self::BUFFER_SIZE
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$binaryReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class must not be instantiated.
|
||||||
|
*/
|
||||||
|
private function __construct() {}
|
||||||
|
}
|
19
src/Symfony/Component/Intl/LICENSE
Normal file
19
src/Symfony/Component/Intl/LICENSE
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2004-2013 Fabien Potencier
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
317
src/Symfony/Component/Intl/Locale/StubLocale.php
Normal file
317
src/Symfony/Component/Intl/Locale/StubLocale.php
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Locale;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Locale;
|
||||||
|
use Symfony\Component\Intl\Exception\NotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Exception\MethodNotImplementedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a stub Locale for the 'en' locale.
|
||||||
|
*
|
||||||
|
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
||||||
|
*/
|
||||||
|
class StubLocale
|
||||||
|
{
|
||||||
|
const DEFAULT_LOCALE = null;
|
||||||
|
|
||||||
|
/** Locale method constants */
|
||||||
|
const ACTUAL_LOCALE = 0;
|
||||||
|
const VALID_LOCALE = 1;
|
||||||
|
|
||||||
|
/** Language tags constants */
|
||||||
|
const LANG_TAG = 'language';
|
||||||
|
const EXTLANG_TAG = 'extlang';
|
||||||
|
const SCRIPT_TAG = 'script';
|
||||||
|
const REGION_TAG = 'region';
|
||||||
|
const VARIANT_TAG = 'variant';
|
||||||
|
const GRANDFATHERED_LANG_TAG = 'grandfathered';
|
||||||
|
const PRIVATE_TAG = 'private';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the best available locale based on HTTP "Accept-Language" header according to RFC 2616
|
||||||
|
*
|
||||||
|
* @param string $header The string containing the "Accept-Language" header value
|
||||||
|
*
|
||||||
|
* @return string The corresponding locale code
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.acceptfromhttp.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function acceptFromHttp($header)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a correctly ordered and delimited locale code
|
||||||
|
*
|
||||||
|
* @param array $subtags A keyed array where the keys identify the particular locale code subtag
|
||||||
|
*
|
||||||
|
* @return string The corresponding locale code
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.composelocale.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function composeLocale(array $subtags)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a language tag filter matches with locale
|
||||||
|
*
|
||||||
|
* @param string $langtag The language tag to check
|
||||||
|
* @param string $locale The language range to check against
|
||||||
|
* @param Boolean $canonicalize
|
||||||
|
*
|
||||||
|
* @return string The corresponding locale code
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.filtermatches.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function filterMatches($langtag, $locale, $canonicalize = false)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the variants for the input locale
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to extract the variants from
|
||||||
|
*
|
||||||
|
* @return array The locale variants
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getallvariants.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getAllVariants($locale)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default locale
|
||||||
|
*
|
||||||
|
* @return string The default locale code. Always returns 'en'
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getdefault.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getDefault()
|
||||||
|
{
|
||||||
|
return 'en';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the localized display name for the locale language
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code to return the display language from
|
||||||
|
* @param string $inLocale Optional format locale code to use to display the language name
|
||||||
|
*
|
||||||
|
* @return string The localized language display name
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getdisplaylanguage.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getDisplayLanguage($locale, $inLocale = null)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the localized display name for the locale
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code to return the display locale name from
|
||||||
|
* @param string $inLocale Optional format locale code to use to display the locale name
|
||||||
|
*
|
||||||
|
* @return string The localized locale display name
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getdisplayname.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getDisplayName($locale, $inLocale = null)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the localized display name for the locale region
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code to return the display region from
|
||||||
|
* @param string $inLocale Optional format locale code to use to display the region name
|
||||||
|
*
|
||||||
|
* @return string The localized region display name
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getdisplayregion.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getDisplayRegion($locale, $inLocale = null)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the localized display name for the locale script
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code to return the display script from
|
||||||
|
* @param string $inLocale Optional format locale code to use to display the script name
|
||||||
|
*
|
||||||
|
* @return string The localized script display name
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getdisplayscript.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getDisplayScript($locale, $inLocale = null)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the localized display name for the locale variant
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code to return the display variant from
|
||||||
|
* @param string $inLocale Optional format locale code to use to display the variant name
|
||||||
|
*
|
||||||
|
* @return string The localized variant display name
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getdisplayvariant.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getDisplayVariant($locale, $inLocale = null)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the keywords for the locale
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code to extract the keywords from
|
||||||
|
*
|
||||||
|
* @return array Associative array with the extracted variants
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getkeywords.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getKeywords($locale)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the primary language for the locale
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code to extract the language code from
|
||||||
|
*
|
||||||
|
* @return string|null The extracted language code or null in case of error
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getprimarylanguage.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getPrimaryLanguage($locale)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the region for the locale
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code to extract the region code from
|
||||||
|
*
|
||||||
|
* @return string|null The extracted region code or null if not present
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getregion.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getRegion($locale)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the script for the locale
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code to extract the script code from
|
||||||
|
*
|
||||||
|
* @return string|null The extracted script code or null if not present
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.getscript.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function getScript($locale)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the closest language tag for the locale
|
||||||
|
*
|
||||||
|
* @param array $langtag A list of the language tags to compare to locale
|
||||||
|
* @param string $locale The locale to use as the language range when matching
|
||||||
|
* @param Boolean $canonicalize If true, the arguments will be converted to canonical form before matching
|
||||||
|
* @param string $default The locale to use if no match is found
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.lookup.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function lookup(array $langtag, $locale, $canonicalize = false, $default = null)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an associative array of locale identifier subtags
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code to extract the subtag array from
|
||||||
|
*
|
||||||
|
* @return array Associative array with the extracted subtags
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.parselocale.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function parseLocale($locale)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default runtime locale
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code
|
||||||
|
*
|
||||||
|
* @return Boolean true on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/locale.parselocale.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public static function setDefault($locale)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,869 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\NumberFormatter;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\NotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Exception\MethodNotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException;
|
||||||
|
use Symfony\Component\Intl\Globals\StubIntlGlobals;
|
||||||
|
use Symfony\Component\Intl\Intl;
|
||||||
|
use Symfony\Component\Intl\Locale\StubLocale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a stub NumberFormatter for the 'en' locale.
|
||||||
|
*
|
||||||
|
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
||||||
|
*/
|
||||||
|
class StubNumberFormatter
|
||||||
|
{
|
||||||
|
/** Format style constants */
|
||||||
|
const PATTERN_DECIMAL = 0;
|
||||||
|
const DECIMAL = 1;
|
||||||
|
const CURRENCY = 2;
|
||||||
|
const PERCENT = 3;
|
||||||
|
const SCIENTIFIC = 4;
|
||||||
|
const SPELLOUT = 5;
|
||||||
|
const ORDINAL = 6;
|
||||||
|
const DURATION = 7;
|
||||||
|
const PATTERN_RULEBASED = 9;
|
||||||
|
const IGNORE = 0;
|
||||||
|
const DEFAULT_STYLE = 1;
|
||||||
|
|
||||||
|
/** Format type constants */
|
||||||
|
const TYPE_DEFAULT = 0;
|
||||||
|
const TYPE_INT32 = 1;
|
||||||
|
const TYPE_INT64 = 2;
|
||||||
|
const TYPE_DOUBLE = 3;
|
||||||
|
const TYPE_CURRENCY = 4;
|
||||||
|
|
||||||
|
/** Numeric attribute constants */
|
||||||
|
const PARSE_INT_ONLY = 0;
|
||||||
|
const GROUPING_USED = 1;
|
||||||
|
const DECIMAL_ALWAYS_SHOWN = 2;
|
||||||
|
const MAX_INTEGER_DIGITS = 3;
|
||||||
|
const MIN_INTEGER_DIGITS = 4;
|
||||||
|
const INTEGER_DIGITS = 5;
|
||||||
|
const MAX_FRACTION_DIGITS = 6;
|
||||||
|
const MIN_FRACTION_DIGITS = 7;
|
||||||
|
const FRACTION_DIGITS = 8;
|
||||||
|
const MULTIPLIER = 9;
|
||||||
|
const GROUPING_SIZE = 10;
|
||||||
|
const ROUNDING_MODE = 11;
|
||||||
|
const ROUNDING_INCREMENT = 12;
|
||||||
|
const FORMAT_WIDTH = 13;
|
||||||
|
const PADDING_POSITION = 14;
|
||||||
|
const SECONDARY_GROUPING_SIZE = 15;
|
||||||
|
const SIGNIFICANT_DIGITS_USED = 16;
|
||||||
|
const MIN_SIGNIFICANT_DIGITS = 17;
|
||||||
|
const MAX_SIGNIFICANT_DIGITS = 18;
|
||||||
|
const LENIENT_PARSE = 19;
|
||||||
|
|
||||||
|
/** Text attribute constants */
|
||||||
|
const POSITIVE_PREFIX = 0;
|
||||||
|
const POSITIVE_SUFFIX = 1;
|
||||||
|
const NEGATIVE_PREFIX = 2;
|
||||||
|
const NEGATIVE_SUFFIX = 3;
|
||||||
|
const PADDING_CHARACTER = 4;
|
||||||
|
const CURRENCY_CODE = 5;
|
||||||
|
const DEFAULT_RULESET = 6;
|
||||||
|
const PUBLIC_RULESETS = 7;
|
||||||
|
|
||||||
|
/** Format symbol constants */
|
||||||
|
const DECIMAL_SEPARATOR_SYMBOL = 0;
|
||||||
|
const GROUPING_SEPARATOR_SYMBOL = 1;
|
||||||
|
const PATTERN_SEPARATOR_SYMBOL = 2;
|
||||||
|
const PERCENT_SYMBOL = 3;
|
||||||
|
const ZERO_DIGIT_SYMBOL = 4;
|
||||||
|
const DIGIT_SYMBOL = 5;
|
||||||
|
const MINUS_SIGN_SYMBOL = 6;
|
||||||
|
const PLUS_SIGN_SYMBOL = 7;
|
||||||
|
const CURRENCY_SYMBOL = 8;
|
||||||
|
const INTL_CURRENCY_SYMBOL = 9;
|
||||||
|
const MONETARY_SEPARATOR_SYMBOL = 10;
|
||||||
|
const EXPONENTIAL_SYMBOL = 11;
|
||||||
|
const PERMILL_SYMBOL = 12;
|
||||||
|
const PAD_ESCAPE_SYMBOL = 13;
|
||||||
|
const INFINITY_SYMBOL = 14;
|
||||||
|
const NAN_SYMBOL = 15;
|
||||||
|
const SIGNIFICANT_DIGIT_SYMBOL = 16;
|
||||||
|
const MONETARY_GROUPING_SEPARATOR_SYMBOL = 17;
|
||||||
|
|
||||||
|
/** Rounding mode values used by NumberFormatter::setAttribute() with NumberFormatter::ROUNDING_MODE attribute */
|
||||||
|
const ROUND_CEILING = 0;
|
||||||
|
const ROUND_FLOOR = 1;
|
||||||
|
const ROUND_DOWN = 2;
|
||||||
|
const ROUND_UP = 3;
|
||||||
|
const ROUND_HALFEVEN = 4;
|
||||||
|
const ROUND_HALFDOWN = 5;
|
||||||
|
const ROUND_HALFUP = 6;
|
||||||
|
|
||||||
|
/** Pad position values used by NumberFormatter::setAttribute() with NumberFormatter::PADDING_POSITION attribute */
|
||||||
|
const PAD_BEFORE_PREFIX = 0;
|
||||||
|
const PAD_AFTER_PREFIX = 1;
|
||||||
|
const PAD_BEFORE_SUFFIX = 2;
|
||||||
|
const PAD_AFTER_SUFFIX = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The error code from the last operation
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
protected $errorCode = StubIntlGlobals::U_ZERO_ERROR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The error message from the last operation
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $errorMessage = 'U_ZERO_ERROR';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $style;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default values for the en locale
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $attributes = array(
|
||||||
|
self::FRACTION_DIGITS => 0,
|
||||||
|
self::GROUPING_USED => 1,
|
||||||
|
self::ROUNDING_MODE => self::ROUND_HALFEVEN
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the initialized attributes code
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $initializedAttributes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The supported styles to the constructor $styles argument
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $supportedStyles = array(
|
||||||
|
'CURRENCY' => self::CURRENCY,
|
||||||
|
'DECIMAL' => self::DECIMAL
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported attributes to the setAttribute() $attr argument
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $supportedAttributes = array(
|
||||||
|
'FRACTION_DIGITS' => self::FRACTION_DIGITS,
|
||||||
|
'GROUPING_USED' => self::GROUPING_USED,
|
||||||
|
'ROUNDING_MODE' => self::ROUNDING_MODE
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The available rounding modes for setAttribute() usage with
|
||||||
|
* StubNumberFormatter::ROUNDING_MODE. StubNumberFormatter::ROUND_DOWN
|
||||||
|
* and StubNumberFormatter::ROUND_UP does not have a PHP only equivalent
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $roundingModes = array(
|
||||||
|
'ROUND_HALFEVEN' => self::ROUND_HALFEVEN,
|
||||||
|
'ROUND_HALFDOWN' => self::ROUND_HALFDOWN,
|
||||||
|
'ROUND_HALFUP' => self::ROUND_HALFUP
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mapping between NumberFormatter rounding modes to the available
|
||||||
|
* modes in PHP's round() function.
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/function.round.php
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $phpRoundingMap = array(
|
||||||
|
self::ROUND_HALFDOWN => \PHP_ROUND_HALF_DOWN,
|
||||||
|
self::ROUND_HALFEVEN => \PHP_ROUND_HALF_EVEN,
|
||||||
|
self::ROUND_HALFUP => \PHP_ROUND_HALF_UP
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum values of the integer type in 32 bit platforms.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $int32Range = array(
|
||||||
|
'positive' => 2147483647,
|
||||||
|
'negative' => -2147483648
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum values of the integer type in 64 bit platforms.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $int64Range = array(
|
||||||
|
'positive' => 9223372036854775807,
|
||||||
|
'negative' => -9223372036854775808
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code
|
||||||
|
* @param int $style Style of the formatting, one of the format style constants
|
||||||
|
* @param string $pattern A pattern string in case $style is NumberFormat::PATTERN_DECIMAL or
|
||||||
|
* NumberFormat::PATTERN_RULEBASED. It must conform to the syntax
|
||||||
|
* described in the ICU DecimalFormat or ICU RuleBasedNumberFormat documentation
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.create.php
|
||||||
|
* @see http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details
|
||||||
|
* @see http://www.icu-project.org/apiref/icu4c/classRuleBasedNumberFormat.html#_details
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When $locale different than 'en' is passed
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When the $style is not supported
|
||||||
|
* @throws MethodArgumentNotImplementedException When the pattern value is different than null
|
||||||
|
*/
|
||||||
|
public function __construct($locale = 'en', $style = null, $pattern = null)
|
||||||
|
{
|
||||||
|
if ('en' != $locale) {
|
||||||
|
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'locale', $locale, 'Only the \'en\' locale is supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_array($style, self::$supportedStyles)) {
|
||||||
|
$message = sprintf('The available styles are: %s.', implode(', ', array_keys(self::$supportedStyles)));
|
||||||
|
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'style', $style, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $pattern) {
|
||||||
|
throw new MethodArgumentNotImplementedException(__METHOD__, 'pattern');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->locale = $locale;
|
||||||
|
$this->style = $style;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static constructor
|
||||||
|
*
|
||||||
|
* @param string $locale The locale code
|
||||||
|
* @param int $style Style of the formatting, one of the format style constants
|
||||||
|
* @param string $pattern A pattern string in case $style is NumberFormat::PATTERN_DECIMAL or
|
||||||
|
* NumberFormat::PATTERN_RULEBASED. It must conform to the syntax
|
||||||
|
* described in the ICU DecimalFormat or ICU RuleBasedNumberFormat documentation
|
||||||
|
*
|
||||||
|
* @return StubNumberFormatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.create.php
|
||||||
|
* @see http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details
|
||||||
|
* @see http://www.icu-project.org/apiref/icu4c/classRuleBasedNumberFormat.html#_details
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When $locale different than 'en' is passed
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When the $style is not supported
|
||||||
|
* @throws MethodArgumentNotImplementedException When the pattern value is different than null
|
||||||
|
*/
|
||||||
|
public static function create($locale = 'en', $style = null, $pattern = null)
|
||||||
|
{
|
||||||
|
return new self($locale, $style, $pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a currency value
|
||||||
|
*
|
||||||
|
* @param float $value The numeric currency value
|
||||||
|
* @param string $currency The 3-letter ISO 4217 currency code indicating the currency to use
|
||||||
|
*
|
||||||
|
* @return string The formatted currency value
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.formatcurrency.php
|
||||||
|
* @see http://www.iso.org/iso/support/faqs/faqs_widely_used_standards/widely_used_standards_other/currency_codes/currency_codes_list-1.htm
|
||||||
|
*/
|
||||||
|
public function formatCurrency($value, $currency)
|
||||||
|
{
|
||||||
|
if ($this->style == self::DECIMAL) {
|
||||||
|
return $this->format($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$symbol = Intl::getCurrencyBundle()->getCurrencySymbol('en', $currency);
|
||||||
|
$fractionDigits = Intl::getCurrencyBundle()->getFractionDigits($currency);
|
||||||
|
|
||||||
|
$value = $this->roundCurrency($value, $currency);
|
||||||
|
|
||||||
|
$negative = false;
|
||||||
|
if (0 > $value) {
|
||||||
|
$negative = true;
|
||||||
|
$value *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = $this->formatNumber($value, $fractionDigits);
|
||||||
|
|
||||||
|
$ret = $symbol.$value;
|
||||||
|
|
||||||
|
return $negative ? '('.$ret.')' : $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a number
|
||||||
|
*
|
||||||
|
* @param number $value The value to format
|
||||||
|
* @param int $type Type of the formatting, one of the format type constants
|
||||||
|
*
|
||||||
|
* @return Boolean|string The formatted value or false on error
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.format.php
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException If the method is called with the class $style 'CURRENCY'
|
||||||
|
* @throws MethodArgumentNotImplementedException If the $type is different than TYPE_DEFAULT
|
||||||
|
*/
|
||||||
|
public function format($value, $type = self::TYPE_DEFAULT)
|
||||||
|
{
|
||||||
|
// The original NumberFormatter does not support this format type
|
||||||
|
if ($type == self::TYPE_CURRENCY) {
|
||||||
|
trigger_error(__METHOD__.'(): Unsupported format type '.$type, \E_USER_WARNING);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->style == self::CURRENCY) {
|
||||||
|
throw new NotImplementedException(sprintf(
|
||||||
|
'%s() method does not support the formatting of currencies (instance with CURRENCY style). %s',
|
||||||
|
__METHOD__, NotImplementedException::INTL_INSTALL_MESSAGE
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only the default type is supported.
|
||||||
|
if ($type != self::TYPE_DEFAULT) {
|
||||||
|
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'type', $type, 'Only TYPE_DEFAULT is supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fractionDigits = $this->getAttribute(self::FRACTION_DIGITS);
|
||||||
|
|
||||||
|
$value = $this->round($value, $fractionDigits);
|
||||||
|
$value = $this->formatNumber($value, $fractionDigits);
|
||||||
|
|
||||||
|
// behave like the intl extension
|
||||||
|
$this->resetError();
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an attribute value
|
||||||
|
*
|
||||||
|
* @param int $attr An attribute specifier, one of the numeric attribute constants
|
||||||
|
*
|
||||||
|
* @return Boolean|int The attribute value on success or false on error
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.getattribute.php
|
||||||
|
*/
|
||||||
|
public function getAttribute($attr)
|
||||||
|
{
|
||||||
|
return isset($this->attributes[$attr]) ? $this->attributes[$attr] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns formatter's last error code. Always returns the U_ZERO_ERROR class constant value
|
||||||
|
*
|
||||||
|
* @return int The error code from last formatter call
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.geterrorcode.php
|
||||||
|
*/
|
||||||
|
public function getErrorCode()
|
||||||
|
{
|
||||||
|
return $this->errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns formatter's last error message. Always returns the U_ZERO_ERROR_MESSAGE class constant value
|
||||||
|
*
|
||||||
|
* @return string The error message from last formatter call
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.geterrormessage.php
|
||||||
|
*/
|
||||||
|
public function getErrorMessage()
|
||||||
|
{
|
||||||
|
return $this->errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatter's locale
|
||||||
|
*
|
||||||
|
* @param int $type The locale name type to return between valid or actual (StubLocale::VALID_LOCALE or StubLocale::ACTUAL_LOCALE, respectively)
|
||||||
|
*
|
||||||
|
* @return string The locale name used to create the formatter
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.getlocale.php
|
||||||
|
*/
|
||||||
|
public function getLocale($type = StubLocale::ACTUAL_LOCALE)
|
||||||
|
{
|
||||||
|
return $this->locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the formatter's pattern
|
||||||
|
*
|
||||||
|
* @return Boolean|string The pattern string used by the formatter or false on error
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.getpattern.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function getPattern()
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a formatter symbol value
|
||||||
|
*
|
||||||
|
* @param int $attr A symbol specifier, one of the format symbol constants
|
||||||
|
*
|
||||||
|
* @return Boolean|string The symbol value or false on error
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.getsymbol.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function getSymbol($attr)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a formatter text attribute value
|
||||||
|
*
|
||||||
|
* @param int $attr An attribute specifier, one of the text attribute constants
|
||||||
|
*
|
||||||
|
* @return Boolean|string The attribute value or false on error
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.gettextattribute.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function getTextAttribute($attr)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a currency number
|
||||||
|
*
|
||||||
|
* @param string $value The value to parse
|
||||||
|
* @param string $currency Parameter to receive the currency name (reference)
|
||||||
|
* @param int $position Offset to begin the parsing on return this value will hold the offset at which the parsing ended
|
||||||
|
*
|
||||||
|
* @return Boolean|string The parsed numeric value of false on error
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.parsecurrency.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function parseCurrency($value, &$currency, &$position = null)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a number
|
||||||
|
*
|
||||||
|
* @param string $value The value to parse
|
||||||
|
* @param string $type Type of the formatting, one of the format type constants. NumberFormatter::TYPE_DOUBLE by default
|
||||||
|
* @param int $position Offset to begin the parsing on return this value will hold the offset at which the parsing ended
|
||||||
|
*
|
||||||
|
* @return Boolean|string The parsed value of false on error
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.parse.php
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentNotImplementedException When $position different than null, behavior not implemented
|
||||||
|
*/
|
||||||
|
public function parse($value, $type = self::TYPE_DOUBLE, &$position = null)
|
||||||
|
{
|
||||||
|
if ($type == self::TYPE_DEFAULT || $type == self::TYPE_CURRENCY) {
|
||||||
|
trigger_error(__METHOD__.'(): Unsupported format type '.$type, \E_USER_WARNING);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't calculate the position when parsing the value
|
||||||
|
if (null !== $position) {
|
||||||
|
throw new MethodArgumentNotImplementedException(__METHOD__, 'position');
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match('/^([^0-9\-]{0,})(.*)/', $value, $matches);
|
||||||
|
|
||||||
|
// Any string before the numeric value causes error in the parsing
|
||||||
|
if (isset($matches[1]) && !empty($matches[1])) {
|
||||||
|
StubIntlGlobals::setError(StubIntlGlobals::U_PARSE_ERROR, 'Number parsing failed');
|
||||||
|
$this->errorCode = StubIntlGlobals::getErrorCode();
|
||||||
|
$this->errorMessage = StubIntlGlobals::getErrorMessage();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove everything that is not number or dot (.)
|
||||||
|
$value = preg_replace('/[^0-9\.\-]/', '', $value);
|
||||||
|
$value = $this->convertValueDataType($value, $type);
|
||||||
|
|
||||||
|
// behave like the intl extension
|
||||||
|
$this->resetError();
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an attribute
|
||||||
|
*
|
||||||
|
* @param int $attr An attribute specifier, one of the numeric attribute constants
|
||||||
|
* @param int $value The attribute value
|
||||||
|
*
|
||||||
|
* @return Boolean true on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.setattribute.php
|
||||||
|
*
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When the $attr is not supported
|
||||||
|
* @throws MethodArgumentValueNotImplementedException When the $value is not supported
|
||||||
|
*/
|
||||||
|
public function setAttribute($attr, $value)
|
||||||
|
{
|
||||||
|
if (!in_array($attr, self::$supportedAttributes)) {
|
||||||
|
$message = sprintf(
|
||||||
|
'The available attributes are: %s',
|
||||||
|
implode(', ', array_keys(self::$supportedAttributes))
|
||||||
|
);
|
||||||
|
|
||||||
|
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'attr', $value, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$supportedAttributes['ROUNDING_MODE'] == $attr && $this->isInvalidRoundingMode($value)) {
|
||||||
|
$message = sprintf(
|
||||||
|
'The supported values for ROUNDING_MODE are: %s',
|
||||||
|
implode(', ', array_keys(self::$roundingModes))
|
||||||
|
);
|
||||||
|
|
||||||
|
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'attr', $value, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$supportedAttributes['GROUPING_USED'] == $attr) {
|
||||||
|
$value = $this->normalizeGroupingUsedValue($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$supportedAttributes['FRACTION_DIGITS'] == $attr) {
|
||||||
|
$value = $this->normalizeFractionDigitsValue($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->attributes[$attr] = $value;
|
||||||
|
$this->initializedAttributes[$attr] = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the formatter's pattern
|
||||||
|
*
|
||||||
|
* @param string $pattern A pattern string in conformance with the ICU DecimalFormat documentation
|
||||||
|
*
|
||||||
|
* @return Boolean true on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.setpattern.php
|
||||||
|
* @see http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function setPattern($pattern)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the formatter's symbol
|
||||||
|
*
|
||||||
|
* @param int $attr A symbol specifier, one of the format symbol constants
|
||||||
|
* @param string $value The value for the symbol
|
||||||
|
*
|
||||||
|
* @return Boolean true on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.setsymbol.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function setSymbol($attr, $value)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a text attribute
|
||||||
|
*
|
||||||
|
* @param int $attr An attribute specifier, one of the text attribute constants
|
||||||
|
* @param int $value The attribute value
|
||||||
|
*
|
||||||
|
* @return Boolean true on success or false on failure
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/numberformatter.settextattribute.php
|
||||||
|
*
|
||||||
|
* @throws MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function setTextAttribute($attr, $value)
|
||||||
|
{
|
||||||
|
throw new MethodNotImplementedException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the error to the default U_ZERO_ERROR
|
||||||
|
*/
|
||||||
|
protected function resetError()
|
||||||
|
{
|
||||||
|
StubIntlGlobals::setError(StubIntlGlobals::U_ZERO_ERROR);
|
||||||
|
$this->errorCode = StubIntlGlobals::getErrorCode();
|
||||||
|
$this->errorMessage = StubIntlGlobals::getErrorMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rounds a currency value, applying increment rounding if applicable
|
||||||
|
*
|
||||||
|
* When a currency have a rounding increment, an extra round is made after the first one. The rounding factor is
|
||||||
|
* determined in the ICU data and is explained as of:
|
||||||
|
*
|
||||||
|
* "the rounding increment is given in units of 10^(-fraction_digits)"
|
||||||
|
*
|
||||||
|
* The only actual rounding data as of this writing, is CHF.
|
||||||
|
*
|
||||||
|
* @param float $value The numeric currency value
|
||||||
|
* @param string $currency The 3-letter ISO 4217 currency code indicating the currency to use
|
||||||
|
*
|
||||||
|
* @return string The rounded numeric currency value
|
||||||
|
*
|
||||||
|
* @see http://en.wikipedia.org/wiki/Swedish_rounding
|
||||||
|
* @see http://www.docjar.com/html/api/com/ibm/icu/util/Currency.java.html#1007
|
||||||
|
*/
|
||||||
|
private function roundCurrency($value, $currency)
|
||||||
|
{
|
||||||
|
$fractionDigits = Intl::getCurrencyBundle()->getFractionDigits($currency);
|
||||||
|
$roundingIncrement = Intl::getCurrencyBundle()->getRoundingIncrement($currency);
|
||||||
|
|
||||||
|
// Round with the formatter rounding mode
|
||||||
|
$value = $this->round($value, $fractionDigits);
|
||||||
|
|
||||||
|
// Swiss rounding
|
||||||
|
if (0 < $roundingIncrement && 0 < $fractionDigits) {
|
||||||
|
$roundingFactor = $roundingIncrement / pow(10, $fractionDigits);
|
||||||
|
$value = round($value / $roundingFactor) * $roundingFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rounds a value.
|
||||||
|
*
|
||||||
|
* @param integer|float $value The value to round
|
||||||
|
* @param int $precision The number of decimal digits to round to
|
||||||
|
*
|
||||||
|
* @return integer|float The rounded value
|
||||||
|
*/
|
||||||
|
private function round($value, $precision)
|
||||||
|
{
|
||||||
|
$precision = $this->getUnitializedPrecision($value, $precision);
|
||||||
|
|
||||||
|
$roundingMode = self::$phpRoundingMap[$this->getAttribute(self::ROUNDING_MODE)];
|
||||||
|
$value = round($value, $precision, $roundingMode);
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a number.
|
||||||
|
*
|
||||||
|
* @param integer|float $value The numeric value to format
|
||||||
|
* @param int $precision The number of decimal digits to use
|
||||||
|
*
|
||||||
|
* @return string The formatted number
|
||||||
|
*/
|
||||||
|
private function formatNumber($value, $precision)
|
||||||
|
{
|
||||||
|
$precision = $this->getUnitializedPrecision($value, $precision);
|
||||||
|
|
||||||
|
return number_format($value, $precision, '.', $this->getAttribute(self::GROUPING_USED) ? ',' : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the precision value if the the DECIMAL style is being used and the FRACTION_DIGITS attribute is unitialized.
|
||||||
|
*
|
||||||
|
* @param integer|float $value The value to get the precision from if the FRACTION_DIGITS attribute is unitialized
|
||||||
|
* @param int $precision The precision value to returns if the FRACTION_DIGITS attribute is initialized
|
||||||
|
*
|
||||||
|
* @return int The precision value
|
||||||
|
*/
|
||||||
|
private function getUnitializedPrecision($value, $precision)
|
||||||
|
{
|
||||||
|
if ($this->style == self::CURRENCY) {
|
||||||
|
return $precision;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->isInitializedAttribute(self::FRACTION_DIGITS)) {
|
||||||
|
preg_match('/.*\.(.*)/', (string) $value, $digits);
|
||||||
|
if (isset($digits[1])) {
|
||||||
|
$precision = strlen($digits[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $precision;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the attribute is initialized (value set by client code).
|
||||||
|
*
|
||||||
|
* @param string $attr The attribute name
|
||||||
|
*
|
||||||
|
* @return Boolean true if the value was set by client, false otherwise
|
||||||
|
*/
|
||||||
|
private function isInitializedAttribute($attr)
|
||||||
|
{
|
||||||
|
return isset($this->initializedAttributes[$attr]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the numeric value using the $type to convert to the right data type.
|
||||||
|
*
|
||||||
|
* @param mixed $value The value to be converted
|
||||||
|
* @param int $type The type to convert. Can be TYPE_DOUBLE (float) or TYPE_INT32 (int)
|
||||||
|
*
|
||||||
|
* @return integer|float The converted value
|
||||||
|
*/
|
||||||
|
private function convertValueDataType($value, $type)
|
||||||
|
{
|
||||||
|
if ($type == self::TYPE_DOUBLE) {
|
||||||
|
$value = (float) $value;
|
||||||
|
} elseif ($type == self::TYPE_INT32) {
|
||||||
|
$value = $this->getInt32Value($value);
|
||||||
|
} elseif ($type == self::TYPE_INT64) {
|
||||||
|
$value = $this->getInt64Value($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the value data type to int or returns false if the value is out of the integer value range.
|
||||||
|
*
|
||||||
|
* @param mixed $value The value to be converted
|
||||||
|
*
|
||||||
|
* @return int The converted value
|
||||||
|
*/
|
||||||
|
private function getInt32Value($value)
|
||||||
|
{
|
||||||
|
if ($value > self::$int32Range['positive'] || $value < self::$int32Range['negative']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the value data type to int or returns false if the value is out of the integer value range.
|
||||||
|
*
|
||||||
|
* @param mixed $value The value to be converted
|
||||||
|
*
|
||||||
|
* @return int|float The converted value
|
||||||
|
*
|
||||||
|
* @see https://bugs.php.net/bug.php?id=59597 Bug #59597
|
||||||
|
*/
|
||||||
|
private function getInt64Value($value)
|
||||||
|
{
|
||||||
|
if ($value > self::$int64Range['positive'] || $value < self::$int64Range['negative']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PHP_INT_SIZE !== 8 && ($value > self::$int32Range['positive'] || $value <= self::$int32Range['negative'])) {
|
||||||
|
// Bug #59597 was fixed on PHP 5.3.14 and 5.4.4
|
||||||
|
// The negative PHP_INT_MAX was being converted to float
|
||||||
|
if (
|
||||||
|
$value == self::$int32Range['negative'] &&
|
||||||
|
(
|
||||||
|
(version_compare(PHP_VERSION, '5.4.0', '<') && version_compare(PHP_VERSION, '5.3.14', '>=')) ||
|
||||||
|
version_compare(PHP_VERSION, '5.4.4', '>=')
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return (int) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (float) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PHP_INT_SIZE === 8) {
|
||||||
|
// Bug #59597 was fixed on PHP 5.3.14 and 5.4.4
|
||||||
|
// A 32 bit integer was being generated instead of a 64 bit integer
|
||||||
|
if (
|
||||||
|
($value > self::$int32Range['positive'] || $value < self::$int32Range['negative']) &&
|
||||||
|
(
|
||||||
|
(version_compare(PHP_VERSION, '5.3.14', '<')) ||
|
||||||
|
(version_compare(PHP_VERSION, '5.4.0', '>=') && version_compare(PHP_VERSION, '5.4.4', '<'))
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
$value = (-2147483648 - ($value % -2147483648)) * ($value / abs($value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the rounding mode is invalid.
|
||||||
|
*
|
||||||
|
* @param int $value The rounding mode value to check
|
||||||
|
*
|
||||||
|
* @return Boolean true if the rounding mode is invalid, false otherwise
|
||||||
|
*/
|
||||||
|
private function isInvalidRoundingMode($value)
|
||||||
|
{
|
||||||
|
if (in_array($value, self::$roundingModes, true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the normalized value for the GROUPING_USED attribute. Any value that can be converted to int will be
|
||||||
|
* cast to Boolean and then to int again. This way, negative values are converted to 1 and string values to 0.
|
||||||
|
*
|
||||||
|
* @param mixed $value The value to be normalized
|
||||||
|
*
|
||||||
|
* @return int The normalized value for the attribute (0 or 1)
|
||||||
|
*/
|
||||||
|
private function normalizeGroupingUsedValue($value)
|
||||||
|
{
|
||||||
|
return (int) (Boolean) (int) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the normalized value for the FRACTION_DIGITS attribute. The value is converted to int and if negative,
|
||||||
|
* the returned value will be 0.
|
||||||
|
*
|
||||||
|
* @param mixed $value The value to be normalized
|
||||||
|
*
|
||||||
|
* @return int The normalized value for the attribute
|
||||||
|
*/
|
||||||
|
private function normalizeFractionDigitsValue($value)
|
||||||
|
{
|
||||||
|
$value = (int) $value;
|
||||||
|
|
||||||
|
return (0 > $value) ? 0 : $value;
|
||||||
|
}
|
||||||
|
}
|
195
src/Symfony/Component/Intl/README.md
Normal file
195
src/Symfony/Component/Intl/README.md
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
Intl Component
|
||||||
|
=============
|
||||||
|
|
||||||
|
A PHP replacement layer for the C intl extension that includes additional data
|
||||||
|
from the ICU library.
|
||||||
|
|
||||||
|
The replacement layer is limited to the locale "en". If you want to use other
|
||||||
|
locales, you should [install the intl extension] [10] instead.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
You can install the component in two different ways:
|
||||||
|
|
||||||
|
* Using the official Git repository (https://github.com/symfony/Intl);
|
||||||
|
* [Install it via Composer] [0] (`symfony/intl` on [Packagist] [1]).
|
||||||
|
|
||||||
|
If you install the component via Composer, the following classes and functions
|
||||||
|
of the intl extension will be automatically provided if the intl extension is
|
||||||
|
not loaded:
|
||||||
|
|
||||||
|
* [`\Locale`] [2]
|
||||||
|
* [`\NumberFormatter`] [3]
|
||||||
|
* [`\IntlDateFormatter`] [4]
|
||||||
|
* [`\Collator`] [5]
|
||||||
|
* [`intl_is_failure()`] [6]
|
||||||
|
* [`intl_get_error_code()`] [7]
|
||||||
|
* [`intl_get_error_message()`] [8]
|
||||||
|
* [`intl_error_name()`] [9]
|
||||||
|
|
||||||
|
If you don't use Composer but the Symfony ClassLoader component, you need to
|
||||||
|
load them manually by adding the following lines to your autoload code:
|
||||||
|
|
||||||
|
if (!function_exists('intl_is_failure')) {
|
||||||
|
require '/path/to/Icu/Resources/stubs/functions.php';
|
||||||
|
|
||||||
|
$loader->registerPrefixFallback('/path/to/Icu/Resources/stubs');
|
||||||
|
}
|
||||||
|
|
||||||
|
Stubbed Classes
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The stubbed classes of the intl extension are limited to the locale "en" and
|
||||||
|
will throw an exception if you try to use a different locale. For using other
|
||||||
|
locales, [install the intl extension] [10] instead.
|
||||||
|
|
||||||
|
### Locale
|
||||||
|
|
||||||
|
The only method supported in the [´\Locale`] [2] class is `getDefault()` and
|
||||||
|
will always return "en". All other methods will throw an exception when used.
|
||||||
|
|
||||||
|
### NumberFormatter
|
||||||
|
|
||||||
|
Numbers can be formatted with the [`\NumberFormatter`] [3] class. The following
|
||||||
|
methods are supported. All other methods are not supported and will throw an
|
||||||
|
exception when used.
|
||||||
|
|
||||||
|
##### __construct($locale = 'en', $style = null, $pattern = null)
|
||||||
|
|
||||||
|
The only supported locale is "en". The supported styles are
|
||||||
|
`\NumberFormatter::DECIMAL` and `\NumberFormatter::CURRENCY`. The argument
|
||||||
|
`$pattern` may not be used.
|
||||||
|
|
||||||
|
##### ::create($locale = 'en', $style = null, $pattern = null)
|
||||||
|
|
||||||
|
See `__construct()`.
|
||||||
|
|
||||||
|
##### formatCurrency($value, $currency)
|
||||||
|
|
||||||
|
Fully supported.
|
||||||
|
|
||||||
|
##### format($value, $type = \NumberFormatter::TYPE_DEFAULT)
|
||||||
|
|
||||||
|
Only type `\NumberFormatter::TYPE_DEFAULT` is supported.
|
||||||
|
|
||||||
|
##### getAttribute($attr)
|
||||||
|
|
||||||
|
Fully supported.
|
||||||
|
|
||||||
|
##### getErrorCode()
|
||||||
|
|
||||||
|
Fully supported.
|
||||||
|
|
||||||
|
##### getErrorMessage()
|
||||||
|
|
||||||
|
Fully supported.
|
||||||
|
|
||||||
|
##### getLocale($type = \Locale::ACTUAL_LOCALE)
|
||||||
|
|
||||||
|
The parameter `$type` is ignored.
|
||||||
|
|
||||||
|
##### parse($value, $type = \NumberFormatter::TYPE_DOUBLE, &$position = null)
|
||||||
|
|
||||||
|
The supported types are `\NumberFormatter::TYPE_DOUBLE`,
|
||||||
|
`\NumberFormatter::TYPE_INT32` and `\NumberFormatter::TYPE_INT64`. The
|
||||||
|
parameter `$position` must always be `null`.
|
||||||
|
|
||||||
|
##### setAttribute($attr, $value)
|
||||||
|
|
||||||
|
The only supported attributes are `\NumberFormatter::FRACTION_DIGITS`,
|
||||||
|
`\NumberFormatter::GROUPING_USED` and `\NumberFormatter::ROUNDING_MODE`.
|
||||||
|
|
||||||
|
The only supported rounding modes are `\NumberFormatter::ROUND_HALFEVEN`,
|
||||||
|
`\NumberFormatter::ROUND_HALFDOWN` and `\NumberFormatter::ROUND_HALFUP`.
|
||||||
|
|
||||||
|
Included Resource Bundles
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
The ICU data is located in several "resource bundles". You can access a PHP
|
||||||
|
wrapper of these bundles through the static Intl class.
|
||||||
|
|
||||||
|
Languages and Scripts
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The translations of language and script names can be found in the language
|
||||||
|
bundle.
|
||||||
|
|
||||||
|
$languages = Intl::getLanguageBundle()->getLanguageNames('en');
|
||||||
|
// => array('ab' => 'Abkhazian', ...)
|
||||||
|
|
||||||
|
$language = Intl::getLanguageBundle()->getLanguageName('en', 'de');
|
||||||
|
// => 'German'
|
||||||
|
|
||||||
|
$language = Intl::getLanguageBundle()->getLanguageName('en', 'de', 'AT);
|
||||||
|
// => 'Austrian German'
|
||||||
|
|
||||||
|
$scripts = Intl::getLanguageBundle()->getScriptNames('en');
|
||||||
|
// => array('Arab' => 'Arabic', ...)
|
||||||
|
|
||||||
|
$script = Intl::getLanguageBundle()->getScriptName('en', 'Hans');
|
||||||
|
// => 'Simplified'
|
||||||
|
|
||||||
|
Countries
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
The translations of country names can be found in the region bundle.
|
||||||
|
|
||||||
|
$countries = Intl::getRegionBundle()->getCountryNames('en');
|
||||||
|
// => array('AF' => 'Afghanistan', ...)
|
||||||
|
|
||||||
|
$country = Intl::getRegionBundle()->getCountryName('en', 'GB');
|
||||||
|
// => 'United Kingdom'
|
||||||
|
|
||||||
|
Locales
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
The translations of locale names can be found in the locale bundle.
|
||||||
|
|
||||||
|
$locales = Intl::getLocaleBundle()->getLocaleNames('en');
|
||||||
|
// => array('af' => 'Afrikaans', ...)
|
||||||
|
|
||||||
|
$locale = Intl::getLocaleBundle()->getLocaleName('en', 'zh_Hans_MO');
|
||||||
|
// => 'Chinese (Simplified, Macau SAR China)'
|
||||||
|
|
||||||
|
Currencies
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
The translations of currency names and other currency-related information can
|
||||||
|
be found in the currency bundle.
|
||||||
|
|
||||||
|
$currencies = Intl::getCurrencyBundle()->getCurrencyNames('en');
|
||||||
|
// => array('AFN' => 'Afghan Afghani', ...)
|
||||||
|
|
||||||
|
$currency = Intl::getCurrencyBundle()->getCurrencyNames('en', 'INR');
|
||||||
|
// => 'Indian Rupee'
|
||||||
|
|
||||||
|
$symbol = Intl::getCurrencyBundle()->getCurrencyNames('en', 'INR');
|
||||||
|
// => '₹'
|
||||||
|
|
||||||
|
$fractionDigits = Intl::getCurrencyBundle()->getFractionDigits('INR');
|
||||||
|
// => 2
|
||||||
|
|
||||||
|
$roundingIncrement = Intl::getCurrencyBundle()->getRoundingIncrement('INR');
|
||||||
|
// => 0
|
||||||
|
|
||||||
|
Resources
|
||||||
|
---------
|
||||||
|
|
||||||
|
You can run the unit tests with the following command:
|
||||||
|
|
||||||
|
$ cd path/to/Symfony/Component/Intl/
|
||||||
|
$ composer.phar install --dev
|
||||||
|
$ phpunit
|
||||||
|
|
||||||
|
[0]: /components/using_components
|
||||||
|
[1]: https://packagist.org/packages/symfony/intl
|
||||||
|
[2]: http://www.php.net/manual/en/class.locale.php
|
||||||
|
[3]: http://www.php.net/manual/en/class.numberformatter.php
|
||||||
|
[4]: http://www.php.net/manual/en/class.intldateformatter.php
|
||||||
|
[5]: http://www.php.net/manual/en/class.collator.php
|
||||||
|
[6]: http://www.php.net/manual/en/function.intl-error-name.php
|
||||||
|
[7]: http://www.php.net/manual/en/function.intl-get-error-code.php
|
||||||
|
[8]: http://www.php.net/manual/en/function.intl-get-error-message.php
|
||||||
|
[9]: http://www.php.net/manual/en/function.intl-is-failure.php
|
||||||
|
[10]: http://www.php.net/manual/en/intl.setup.php
|
71
src/Symfony/Component/Intl/ResourceBundle/AbstractBundle.php
Normal file
71
src/Symfony/Component/Intl/ResourceBundle/AbstractBundle.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Intl;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Reader\StructuredBundleReaderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for {@link ResourceBundleInterface} implementations.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
abstract class AbstractBundle implements ResourceBundleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var StructuredBundleReaderInterface
|
||||||
|
*/
|
||||||
|
private $reader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a bundle at the given path using the given reader for reading
|
||||||
|
* bundle entries.
|
||||||
|
*
|
||||||
|
* @param string $path The path to the bundle.
|
||||||
|
* @param StructuredBundleReaderInterface $reader The reader for reading
|
||||||
|
* the bundle.
|
||||||
|
*/
|
||||||
|
public function __construct($path, StructuredBundleReaderInterface $reader)
|
||||||
|
{
|
||||||
|
$this->path = $path;
|
||||||
|
$this->reader = $reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getLocales()
|
||||||
|
{
|
||||||
|
return $this->reader->getLocales($this->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy method for {@link StructuredBundleReaderInterface#read}.
|
||||||
|
*/
|
||||||
|
protected function read($locale)
|
||||||
|
{
|
||||||
|
return $this->reader->read($this->path, $locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy method for {@link StructuredBundleReaderInterface#readEntry}.
|
||||||
|
*/
|
||||||
|
protected function readEntry($locale, array $indices, $mergeFallback = false)
|
||||||
|
{
|
||||||
|
return $this->reader->readEntry($this->path, $locale, $indices, $mergeFallback);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Compiler;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\RuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles .txt resource bundles to binary .res files.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class BundleCompiler implements ResourceBundleCompilerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string The path to the "genrb" executable.
|
||||||
|
*/
|
||||||
|
private $genrb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new compiler based on the "genrb" executable.
|
||||||
|
*
|
||||||
|
* @param string $genrb Optional. The path to the "genrb" executable.
|
||||||
|
*
|
||||||
|
* @throws RuntimeException If the "genrb" cannot be found.
|
||||||
|
*/
|
||||||
|
public function __construct($genrb = 'genrb')
|
||||||
|
{
|
||||||
|
exec('which ' . $genrb, $output, $status);
|
||||||
|
|
||||||
|
if (0 !== $status) {
|
||||||
|
throw new RuntimeException(sprintf(
|
||||||
|
'The command "%s" is not installed',
|
||||||
|
$genrb
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->genrb = $genrb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function compile($sourcePath, $targetDir)
|
||||||
|
{
|
||||||
|
if (is_dir($sourcePath)) {
|
||||||
|
$sourcePath .= '/*.txt';
|
||||||
|
}
|
||||||
|
|
||||||
|
exec($this->genrb.' --quiet -e UTF-8 -d '.$targetDir.' '.$sourcePath, $output, $status);
|
||||||
|
|
||||||
|
if ($status !== 0) {
|
||||||
|
throw new RuntimeException(sprintf(
|
||||||
|
'genrb failed with status %d while compiling %s to %s.',
|
||||||
|
$status,
|
||||||
|
$sourcePath,
|
||||||
|
$targetDir
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Compiler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles a resource bundle.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface ResourceBundleCompilerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compiles a resource bundle at the given source to the given target
|
||||||
|
* directory.
|
||||||
|
*
|
||||||
|
* @param string $sourcePath
|
||||||
|
* @param string $targetDir
|
||||||
|
*/
|
||||||
|
public function compile($sourcePath, $targetDir);
|
||||||
|
}
|
82
src/Symfony/Component/Intl/ResourceBundle/CurrencyBundle.php
Normal file
82
src/Symfony/Component/Intl/ResourceBundle/CurrencyBundle.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of {@link CurrencyBundleInterface}.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class CurrencyBundle extends AbstractBundle implements CurrencyBundleInterface
|
||||||
|
{
|
||||||
|
const INDEX_NAME = 0;
|
||||||
|
|
||||||
|
const INDEX_SYMBOL = 1;
|
||||||
|
|
||||||
|
const INDEX_FRACTION_DIGITS = 2;
|
||||||
|
|
||||||
|
const INDEX_ROUNDING_INCREMENT = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getCurrencySymbol($locale, $currency)
|
||||||
|
{
|
||||||
|
return $this->readEntry($locale, array('Currencies', $currency, static::INDEX_SYMBOL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getCurrencyName($locale, $currency)
|
||||||
|
{
|
||||||
|
return $this->readEntry($locale, array('Currencies', $currency, static::INDEX_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getCurrencyNames($locale)
|
||||||
|
{
|
||||||
|
if (null === ($currencies = $this->readEntry($locale, array('Currencies')))) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($currencies instanceof \Traversable) {
|
||||||
|
$currencies = iterator_to_array($currencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
$index = static::INDEX_NAME;
|
||||||
|
|
||||||
|
array_walk($currencies, function (&$value) use ($index) {
|
||||||
|
$value = $value[$index];
|
||||||
|
});
|
||||||
|
|
||||||
|
return $currencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getFractionDigits($currency)
|
||||||
|
{
|
||||||
|
return $this->readEntry('en', array('Currencies', $currency, static::INDEX_FRACTION_DIGITS));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getRoundingIncrement($currency)
|
||||||
|
{
|
||||||
|
return $this->readEntry('en', array('Currencies', $currency, static::INDEX_ROUNDING_INCREMENT));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives access to currency-related ICU data.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface CurrencyBundleInterface extends ResourceBundleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the symbol used for a currency.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the result in.
|
||||||
|
* @param string $currency A currency code (e.g. "EUR").
|
||||||
|
*
|
||||||
|
* @return string|null The currency symbol or NULL if not found.
|
||||||
|
*/
|
||||||
|
public function getCurrencySymbol($locale, $currency);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of a currency.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the name in.
|
||||||
|
* @param string $currency A currency code (e.g. "EUR").
|
||||||
|
*
|
||||||
|
* @return string|null The name of the currency or NULL if not found.
|
||||||
|
*/
|
||||||
|
public function getCurrencyName($locale, $currency);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the names of all known currencies.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the names in.
|
||||||
|
*
|
||||||
|
* @return string[] A list of currency names indexed by currency codes.
|
||||||
|
*/
|
||||||
|
public function getCurrencyNames($locale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of digits after the comma of a currency.
|
||||||
|
*
|
||||||
|
* @param string $currency A currency code (e.g. "EUR").
|
||||||
|
*
|
||||||
|
* @return integer|null The number of digits after the comma or NULL if not found.
|
||||||
|
*/
|
||||||
|
public function getFractionDigits($currency);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the rounding increment of a currency.
|
||||||
|
*
|
||||||
|
* The rounding increment indicates to which number a currency is rounded.
|
||||||
|
* For example, 1230 rounded to the nearest 50 is 1250. 1.234 rounded to the
|
||||||
|
* nearest 0.65 is 1.3.
|
||||||
|
*
|
||||||
|
* @param string $currency A currency code (e.g. "EUR").
|
||||||
|
*
|
||||||
|
* @return float|integer|null The rounding increment or NULL if not found.
|
||||||
|
*/
|
||||||
|
public function getRoundingIncrement($currency);
|
||||||
|
}
|
99
src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php
Normal file
99
src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of {@link LanguageBundleInterface}.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class LanguageBundle extends AbstractBundle implements LanguageBundleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getLanguageName($locale, $lang, $region = null)
|
||||||
|
{
|
||||||
|
if (null === ($languages = $this->readEntry($locale, array('Languages')))) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some languages are translated together with their region,
|
||||||
|
// i.e. "en_GB" is translated as "British English"
|
||||||
|
if (null !== $region && isset($languages[$lang.'_'.$region])) {
|
||||||
|
return $languages[$lang.'_'.$region];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $languages[$lang];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getLanguageNames($locale)
|
||||||
|
{
|
||||||
|
if (null === ($languages = $this->readEntry($locale, array('Languages')))) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($languages instanceof \Traversable) {
|
||||||
|
$languages = iterator_to_array($languages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $languages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getScriptName($locale, $script, $lang = null)
|
||||||
|
{
|
||||||
|
$data = $this->read($locale);
|
||||||
|
|
||||||
|
// Some languages are translated together with their script,
|
||||||
|
// e.g. "zh_Hans" is translated as "Simplified Chinese"
|
||||||
|
if (null !== $lang && isset($data['Languages'][$lang.'_'.$script])) {
|
||||||
|
$langName = $data['Languages'][$lang.'_'.$script];
|
||||||
|
|
||||||
|
// If the script is appended in braces, extract it, e.g. "zh_Hans"
|
||||||
|
// is translated as "Chinesisch (vereinfacht)" in locale "de"
|
||||||
|
if (strpos($langName, '(') !== false) {
|
||||||
|
list($langName, $scriptName) = preg_split('/[\s()]/', $langName, null, PREG_SPLIT_NO_EMPTY);
|
||||||
|
|
||||||
|
return $scriptName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "af" (Afrikaans) has no "Scripts" block
|
||||||
|
if (!isset($data['Scripts'][$script])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data['Scripts'][$script];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getScriptNames($locale)
|
||||||
|
{
|
||||||
|
if (null === ($scripts = $this->readEntry($locale, array('Scripts')))) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($scripts instanceof \Traversable) {
|
||||||
|
$scripts = iterator_to_array($scripts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $scripts;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives access to language-related ICU data.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface LanguageBundleInterface extends ResourceBundleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the name of a language.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the name in.
|
||||||
|
* @param string $lang A language code (e.g. "en").
|
||||||
|
* @param string|null $region Optional. A region code (e.g. "US").
|
||||||
|
*
|
||||||
|
* @return string|null The name of the language or NULL if not found.
|
||||||
|
*/
|
||||||
|
public function getLanguageName($locale, $lang, $region = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the names of all known languages.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the names in.
|
||||||
|
*
|
||||||
|
* @return string[] A list of language names indexed by language codes.
|
||||||
|
*/
|
||||||
|
public function getLanguageNames($locale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of a script.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the name in.
|
||||||
|
* @param string $script A script code (e.g. "Hans").
|
||||||
|
* @param string $lang Optional. A language code (e.g. "zh").
|
||||||
|
*
|
||||||
|
* @return string|null The name of the script or NULL if not found.
|
||||||
|
*/
|
||||||
|
public function getScriptName($locale, $script, $lang = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the names of all known scripts.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the names in.
|
||||||
|
*
|
||||||
|
* @return string[] A list of script names indexed by script codes.
|
||||||
|
*/
|
||||||
|
public function getScriptNames($locale);
|
||||||
|
}
|
44
src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php
Normal file
44
src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of {@link LocaleBundleInterface}.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class LocaleBundle extends AbstractBundle implements LocaleBundleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getLocaleName($locale, $ofLocale)
|
||||||
|
{
|
||||||
|
return $this->readEntry($locale, array('Locales', $ofLocale));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getLocaleNames($locale)
|
||||||
|
{
|
||||||
|
if (null === ($locales = $this->readEntry($locale, array('Locales')))) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($locales instanceof \Traversable) {
|
||||||
|
$locales = iterator_to_array($locales);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $locales;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives access to locale-related ICU data.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface LocaleBundleInterface extends ResourceBundleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the name of a locale.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the name in.
|
||||||
|
* @param string $ofLocale The locale to return the name of (e.g. "de_AT").
|
||||||
|
*
|
||||||
|
* @return string|null The name of the locale or NULL if not found.
|
||||||
|
*/
|
||||||
|
public function getLocaleName($locale, $ofLocale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the names of all known locales.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the name in.
|
||||||
|
*
|
||||||
|
* @return string[] A list of locale names indexed by locale codes.
|
||||||
|
*/
|
||||||
|
public function getLocaleNames($locale);
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Reader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for {@link BundleReaderInterface} implementations.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
abstract class AbstractBundleReader implements BundleReaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getLocales($path)
|
||||||
|
{
|
||||||
|
$extension = '.' . $this->getFileExtension();
|
||||||
|
$locales = glob($path . '/*' . $extension);
|
||||||
|
|
||||||
|
// Remove file extension and sort
|
||||||
|
array_walk($locales, function (&$locale) use ($extension) { $locale = basename($locale, $extension); });
|
||||||
|
sort($locales);
|
||||||
|
|
||||||
|
return $locales;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the extension of locale files in this bundle.
|
||||||
|
*
|
||||||
|
* @return string The file extension (without leading dot).
|
||||||
|
*/
|
||||||
|
abstract protected function getFileExtension();
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Reader;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\RuntimeException;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Util\ArrayAccessibleResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads binary .res resource bundles.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class BinaryBundleReader extends AbstractBundleReader implements BundleReaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function read($path, $locale)
|
||||||
|
{
|
||||||
|
// Point for future extension: Modify this class so that it works also
|
||||||
|
// if the \ResourceBundle class is not available.
|
||||||
|
$bundle = new \ResourceBundle($locale, $path);
|
||||||
|
|
||||||
|
if (null === $bundle) {
|
||||||
|
throw new RuntimeException(sprintf(
|
||||||
|
'Could not load the resource bundle "%s/%s.res".',
|
||||||
|
$path,
|
||||||
|
$locale
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayAccessibleResourceBundle($bundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function getFileExtension()
|
||||||
|
{
|
||||||
|
return 'res';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Reader;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Util\RingBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class BufferedReader implements BundleReaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var BundleReaderInterface
|
||||||
|
*/
|
||||||
|
private $reader;
|
||||||
|
|
||||||
|
|
||||||
|
private $buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffers a given reader.
|
||||||
|
*
|
||||||
|
* @param BundleReaderInterface $reader The reader to buffer.
|
||||||
|
* @param integer $bufferSize The number of entries to store
|
||||||
|
* in the buffer.
|
||||||
|
*/
|
||||||
|
public function __construct(BundleReaderInterface $reader, $bufferSize)
|
||||||
|
{
|
||||||
|
$this->reader = $reader;
|
||||||
|
$this->buffer = new RingBuffer($bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function read($path, $locale)
|
||||||
|
{
|
||||||
|
$hash = $path . '//' . $locale;
|
||||||
|
|
||||||
|
if (!isset($this->buffer[$hash])) {
|
||||||
|
$this->buffer[$hash] = $this->reader->read($path, $locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->buffer[$hash];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getLocales($path)
|
||||||
|
{
|
||||||
|
return $this->reader->getLocales($path);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Reader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads resource bundle files.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface BundleReaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Reads a resource bundle.
|
||||||
|
*
|
||||||
|
* @param string $path The path to the resource bundle.
|
||||||
|
* @param string $locale The locale to read.
|
||||||
|
*
|
||||||
|
* @return mixed Returns an array or {@link \ArrayAccess} instance for
|
||||||
|
* complex data, a scalar value otherwise.
|
||||||
|
*/
|
||||||
|
public function read($path, $locale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the available locales of a resource bundle.
|
||||||
|
*
|
||||||
|
* @param string $path The path to the resource bundle.
|
||||||
|
*
|
||||||
|
* @return string[] A list of supported locale codes.
|
||||||
|
*/
|
||||||
|
public function getLocales($path);
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Reader;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\InvalidArgumentException;
|
||||||
|
use Symfony\Component\Intl\Exception\RuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads .php resource bundles.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class PhpBundleReader extends AbstractBundleReader implements BundleReaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function read($path, $locale)
|
||||||
|
{
|
||||||
|
if ('en' !== $locale) {
|
||||||
|
throw new InvalidArgumentException('Only the locale "en" is supported.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileName = $path . '/' . $locale . '.php';
|
||||||
|
|
||||||
|
if (!file_exists($fileName)) {
|
||||||
|
throw new RuntimeException(sprintf(
|
||||||
|
'The resource bundle "%s/%s.php" does not exist.',
|
||||||
|
$path,
|
||||||
|
$locale
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_file($fileName)) {
|
||||||
|
throw new RuntimeException(sprintf(
|
||||||
|
'The resource bundle "%s/%s.php" is not a file.',
|
||||||
|
$path,
|
||||||
|
$locale
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return include $fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function getFileExtension()
|
||||||
|
{
|
||||||
|
return 'php';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Reader;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Util\RecursiveArrayAccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A structured reader wrapping an existing resource bundle reader.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @see StructuredResourceBundleBundleReaderInterface
|
||||||
|
*/
|
||||||
|
class StructuredBundleReader implements StructuredBundleReaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var BundleReaderInterface
|
||||||
|
*/
|
||||||
|
private $reader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an entry reader based on the given resource bundle reader.
|
||||||
|
*
|
||||||
|
* @param BundleReaderInterface $reader A resource bundle reader to use.
|
||||||
|
*/
|
||||||
|
public function __construct(BundleReaderInterface $reader)
|
||||||
|
{
|
||||||
|
$this->reader = $reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function read($path, $locale)
|
||||||
|
{
|
||||||
|
return $this->reader->read($path, $locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getLocales($path)
|
||||||
|
{
|
||||||
|
return $this->reader->getLocales($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function readEntry($path, $locale, array $indices, $mergeFallback = true)
|
||||||
|
{
|
||||||
|
$data = $this->reader->read($path, $locale);
|
||||||
|
|
||||||
|
$entry = RecursiveArrayAccess::get($data, $indices);
|
||||||
|
$multivalued = is_array($entry) || $entry instanceof \Traversable;
|
||||||
|
|
||||||
|
if (!($mergeFallback && (null === $entry || $multivalued))) {
|
||||||
|
return $entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== ($fallbackLocale = $this->getFallbackLocale($locale))) {
|
||||||
|
$parentEntry = $this->readEntry($path, $fallbackLocale, $indices, true);
|
||||||
|
|
||||||
|
if ($entry || $parentEntry) {
|
||||||
|
$multivalued = $multivalued || is_array($parentEntry) || $parentEntry instanceof \Traversable;
|
||||||
|
|
||||||
|
if ($multivalued) {
|
||||||
|
if ($entry instanceof \Traversable) {
|
||||||
|
$entry = iterator_to_array($entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($parentEntry instanceof \Traversable) {
|
||||||
|
$parentEntry = iterator_to_array($parentEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry = array_merge(
|
||||||
|
$parentEntry ?: array(),
|
||||||
|
$entry ?: array()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$entry = null === $entry ? $parentEntry : $entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fallback locale for a given locale, if any
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to find the fallback for.
|
||||||
|
*
|
||||||
|
* @return string|null The fallback locale, or null if no parent exists
|
||||||
|
*/
|
||||||
|
private function getFallbackLocale($locale)
|
||||||
|
{
|
||||||
|
if (false === $pos = strrpos($locale, '_')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return substr($locale, 0, $pos);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Reader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads individual entries of a resource file.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface StructuredBundleReaderInterface extends BundleReaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Reads an entry from a resource bundle.
|
||||||
|
*
|
||||||
|
* An entry can be selected from the resource bundle by passing the path
|
||||||
|
* to that entry in the bundle. For example, if the bundle is structured
|
||||||
|
* like this:
|
||||||
|
*
|
||||||
|
* TopLevel
|
||||||
|
* NestedLevel
|
||||||
|
* Entry: Value
|
||||||
|
*
|
||||||
|
* Then the value can be read by calling:
|
||||||
|
*
|
||||||
|
* $reader->readEntry('...', 'en', array('TopLevel', 'NestedLevel', 'Entry'));
|
||||||
|
*
|
||||||
|
* @param string $path The path to the resource bundle.
|
||||||
|
* @param string $locale The locale to read.
|
||||||
|
* @param string[] $indices The indices to read from the bundle.
|
||||||
|
* @param Boolean $mergeFallback Whether to merge the value with the value
|
||||||
|
* from the fallback locale (e.g. "en" for
|
||||||
|
* "en_GB"). Only applicable if the result
|
||||||
|
* is multivalued (array, \ArrayAccess).
|
||||||
|
*
|
||||||
|
* @return mixed Returns an array or {@link \ArrayAccess} instance for
|
||||||
|
* complex data, a scalar value for simple data and NULL
|
||||||
|
* if the given path could not be accessed.
|
||||||
|
*/
|
||||||
|
public function readEntry($path, $locale, array $indices, $mergeFallback = true);
|
||||||
|
}
|
44
src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php
Normal file
44
src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of {@link RegionBundleInterface}.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class RegionBundle extends AbstractBundle implements RegionBundleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getCountryName($locale, $country)
|
||||||
|
{
|
||||||
|
return $this->readEntry($locale, array('Countries', $country));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getCountryNames($locale)
|
||||||
|
{
|
||||||
|
if (null === ($countries = $this->readEntry($locale, array('Countries')))) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($countries instanceof \Traversable) {
|
||||||
|
$countries = iterator_to_array($countries);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $countries;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives access to region-related ICU data.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface RegionBundleInterface extends ResourceBundleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the name of a country.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the name in.
|
||||||
|
* @param string $country A country code (e.g. "US").
|
||||||
|
*
|
||||||
|
* @return string|null The name of the country or NULL if not found.
|
||||||
|
*/
|
||||||
|
public function getCountryName($locale, $country);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the names of all known countries.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale to return the names in.
|
||||||
|
*
|
||||||
|
* @return string[] A list of country names indexed by country codes.
|
||||||
|
*/
|
||||||
|
public function getCountryNames($locale);
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives access to ICU data.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface ResourceBundleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the list of locales that this bundle supports.
|
||||||
|
*
|
||||||
|
* @return string[] A list of locale codes.
|
||||||
|
*/
|
||||||
|
public function getLocales();
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Stub;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\CurrencyBundle;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Reader\StructuredBundleReaderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class StubCurrencyBundle extends CurrencyBundle
|
||||||
|
{
|
||||||
|
public function __construct(StructuredBundleReaderInterface $reader)
|
||||||
|
{
|
||||||
|
parent::__construct(realpath(__DIR__ . '/../../Resources/data/curr'), $reader);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Stub;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\LanguageBundle;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Reader\StructuredBundleReaderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class StubLanguageBundle extends LanguageBundle
|
||||||
|
{
|
||||||
|
public function __construct(StructuredBundleReaderInterface $reader)
|
||||||
|
{
|
||||||
|
parent::__construct(realpath(__DIR__ . '/../../Resources/data/lang'), $reader);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Stub;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\LocaleBundle;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Reader\StructuredBundleReaderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class StubLocaleBundle extends LocaleBundle
|
||||||
|
{
|
||||||
|
public function __construct(StructuredBundleReaderInterface $reader)
|
||||||
|
{
|
||||||
|
parent::__construct(realpath(__DIR__ . '/../../Resources/data/locales'), $reader);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Stub;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Reader\StructuredBundleReaderInterface;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\RegionBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class StubRegionBundle extends RegionBundle
|
||||||
|
{
|
||||||
|
public function __construct(StructuredBundleReaderInterface $reader)
|
||||||
|
{
|
||||||
|
parent::__construct(realpath(__DIR__ . '/../../Resources/data/region'), $reader);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Transformer;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\RuntimeException;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\TransformationRuleInterface;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Writer\PhpBundleWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles a number of resource bundles based on predefined compilation rules.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class BundleTransformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var TransformationRuleInterface[]
|
||||||
|
*/
|
||||||
|
private $rules = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new compilation rule.
|
||||||
|
*
|
||||||
|
* @param TransformationRuleInterface $rule The compilation rule.
|
||||||
|
*/
|
||||||
|
public function addRule(TransformationRuleInterface $rule)
|
||||||
|
{
|
||||||
|
$this->rules[] = $rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the compilation with the given compilation context.
|
||||||
|
*
|
||||||
|
* @param CompilationContextInterface $context The context storing information
|
||||||
|
* needed to run the compilation.
|
||||||
|
*
|
||||||
|
* @throws RuntimeException If any of the files to be compiled by the loaded
|
||||||
|
* compilation rules does not exist.
|
||||||
|
*/
|
||||||
|
public function compileBundles(CompilationContextInterface $context)
|
||||||
|
{
|
||||||
|
$filesystem = $context->getFilesystem();
|
||||||
|
$compiler = $context->getCompiler();
|
||||||
|
|
||||||
|
$filesystem->remove($context->getBinaryDir());
|
||||||
|
$filesystem->mkdir($context->getBinaryDir());
|
||||||
|
|
||||||
|
foreach ($this->rules as $rule) {
|
||||||
|
$filesystem->mkdir($context->getBinaryDir() . '/' . $rule->getBundleName());
|
||||||
|
|
||||||
|
$resources = (array) $rule->beforeCompile($context);
|
||||||
|
|
||||||
|
foreach ($resources as $resource) {
|
||||||
|
if (!file_exists($resource)) {
|
||||||
|
throw new RuntimeException(sprintf(
|
||||||
|
'The file "%s" to be compiled by %s does not exist.',
|
||||||
|
$resource,
|
||||||
|
get_class($rule)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$compiler->compile($resource, $context->getBinaryDir() . '/' . $rule->getBundleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
$rule->afterCompile($context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createStubs(StubbingContextInterface $context)
|
||||||
|
{
|
||||||
|
$filesystem = $context->getFilesystem();
|
||||||
|
$phpWriter = new PhpBundleWriter();
|
||||||
|
|
||||||
|
$filesystem->remove($context->getStubDir());
|
||||||
|
$filesystem->mkdir($context->getStubDir());
|
||||||
|
|
||||||
|
foreach ($this->rules as $rule) {
|
||||||
|
$filesystem->mkdir($context->getStubDir() . '/' . $rule->getBundleName());
|
||||||
|
|
||||||
|
$data = $rule->beforeCreateStub($context);
|
||||||
|
|
||||||
|
$phpWriter->write($context->getStubDir() . '/' . $rule->getBundleName(), 'en', $data);
|
||||||
|
|
||||||
|
$rule->afterCreateStub($context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Transformer;
|
||||||
|
|
||||||
|
use Symfony\Component\Filesystem\Filesystem;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Compiler\ResourceBundleCompilerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of {@link CompilationContextInterface}.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class CompilationContext implements CompilationContextInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sourceDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $binaryDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var FileSystem
|
||||||
|
*/
|
||||||
|
private $filesystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ResourceBundleCompilerInterface
|
||||||
|
*/
|
||||||
|
private $compiler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $icuVersion;
|
||||||
|
|
||||||
|
public function __construct($sourceDir, $binaryDir, Filesystem $filesystem, ResourceBundleCompilerInterface $compiler, $icuVersion)
|
||||||
|
{
|
||||||
|
$this->sourceDir = $sourceDir;
|
||||||
|
$this->binaryDir = $binaryDir;
|
||||||
|
$this->filesystem = $filesystem;
|
||||||
|
$this->compiler = $compiler;
|
||||||
|
$this->icuVersion = $icuVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getSourceDir()
|
||||||
|
{
|
||||||
|
return $this->sourceDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getBinaryDir()
|
||||||
|
{
|
||||||
|
return $this->binaryDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getFilesystem()
|
||||||
|
{
|
||||||
|
return $this->filesystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getCompiler()
|
||||||
|
{
|
||||||
|
return $this->compiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getIcuVersion()
|
||||||
|
{
|
||||||
|
return $this->icuVersion;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Transformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores contextual information for resource bundle compilation.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface CompilationContextInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the directory where the source versions of the resource bundles
|
||||||
|
* are stored.
|
||||||
|
*
|
||||||
|
* @return string An absolute path to a directory.
|
||||||
|
*/
|
||||||
|
public function getSourceDir();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the directory where the binary resource bundles are stored.
|
||||||
|
*
|
||||||
|
* @return string An absolute path to a directory.
|
||||||
|
*/
|
||||||
|
public function getBinaryDir();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a tool for manipulating the filesystem.
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\Filesystem\Filesystem The filesystem manipulator.
|
||||||
|
*/
|
||||||
|
public function getFilesystem();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a resource bundle compiler.
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\Intl\ResourceBundle\Compiler\ResourceBundleCompilerInterface The loaded resource bundle compiler.
|
||||||
|
*/
|
||||||
|
public function getCompiler();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ICU version of the bundles being converted.
|
||||||
|
*
|
||||||
|
* @return string The ICU version string.
|
||||||
|
*/
|
||||||
|
public function getIcuVersion();
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Intl;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\CurrencyBundle;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rule for compiling the currency bundle.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class CurrencyBundleTransformationRule implements TransformationRuleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getBundleName()
|
||||||
|
{
|
||||||
|
return 'curr';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function beforeCompile(CompilationContextInterface $context)
|
||||||
|
{
|
||||||
|
// The currency data is contained in the locales and misc bundles
|
||||||
|
// in ICU <= 4.2
|
||||||
|
if (version_compare($context->getIcuVersion(), '4.2', '<=')) {
|
||||||
|
return array(
|
||||||
|
$context->getSourceDir() . '/misc/supplementalData.txt',
|
||||||
|
$context->getSourceDir() . '/locales'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $context->getSourceDir() . '/curr';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function afterCompile(CompilationContextInterface $context)
|
||||||
|
{
|
||||||
|
// \ResourceBundle does not like locale names with uppercase chars, so rename
|
||||||
|
// the resource file
|
||||||
|
// See: http://bugs.php.net/bug.php?id=54025
|
||||||
|
$fileName = $context->getBinaryDir() . '/curr/supplementalData.res';
|
||||||
|
$fileNameLower = $context->getBinaryDir() . '/curr/supplementaldata.res';
|
||||||
|
|
||||||
|
$context->getFilesystem()->rename($fileName, $fileNameLower);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function beforeCreateStub(StubbingContextInterface $context)
|
||||||
|
{
|
||||||
|
$currencies = array();
|
||||||
|
$currencyBundle = Intl::getCurrencyBundle();
|
||||||
|
|
||||||
|
foreach ($currencyBundle->getCurrencyNames('en') as $code => $name) {
|
||||||
|
$currencies[$code] = array(
|
||||||
|
CurrencyBundle::INDEX_NAME => $name,
|
||||||
|
CurrencyBundle::INDEX_SYMBOL => $currencyBundle->getCurrencySymbol('en', $code),
|
||||||
|
CurrencyBundle::INDEX_FRACTION_DIGITS => $currencyBundle->getFractionDigits($code),
|
||||||
|
CurrencyBundle::INDEX_ROUNDING_INCREMENT => $currencyBundle->getRoundingIncrement($code),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Currencies' => $currencies,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function afterCreateStub(StubbingContextInterface $context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Intl;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rule for compiling the language bundle.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class LanguageBundleTransformationRule implements TransformationRuleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getBundleName()
|
||||||
|
{
|
||||||
|
return 'lang';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function beforeCompile(CompilationContextInterface $context)
|
||||||
|
{
|
||||||
|
// The language data is contained in the locales bundle in ICU <= 4.2
|
||||||
|
if (version_compare($context->getIcuVersion(), '4.2', '<=')) {
|
||||||
|
return $context->getSourceDir() . '/locales';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $context->getSourceDir() . '/lang';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function afterCompile(CompilationContextInterface $context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function beforeCreateStub(StubbingContextInterface $context)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'Languages' => Intl::getLanguageBundle()->getLanguageNames('en'),
|
||||||
|
'Scripts' => Intl::getLanguageBundle()->getScriptNames('en'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function afterCreateStub(StubbingContextInterface $context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,251 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\RuntimeException;
|
||||||
|
use Symfony\Component\Intl\Intl;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Writer\TextBundleWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rule for compiling the locale bundle.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class LocaleBundleTransformationRule implements TransformationRuleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Symfony\Component\Intl\ResourceBundle\LanguageBundleInterface
|
||||||
|
*/
|
||||||
|
private $languageBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Symfony\Component\Intl\ResourceBundle\RegionBundleInterface
|
||||||
|
*/
|
||||||
|
private $regionBundle;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->languageBundle = Intl::getLanguageBundle();
|
||||||
|
$this->regionBundle = Intl::getRegionBundle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getBundleName()
|
||||||
|
{
|
||||||
|
return 'locales';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function beforeCompile(CompilationContextInterface $context)
|
||||||
|
{
|
||||||
|
$tempDir = sys_get_temp_dir() . '/icu-data-locales';
|
||||||
|
|
||||||
|
$context->getFilesystem()->remove($tempDir);
|
||||||
|
$context->getFilesystem()->mkdir($tempDir);
|
||||||
|
|
||||||
|
$this->generateTextFiles($tempDir, $this->scanLocales($context));
|
||||||
|
|
||||||
|
return $tempDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function afterCompile(CompilationContextInterface $context)
|
||||||
|
{
|
||||||
|
$context->getFilesystem()->remove(sys_get_temp_dir() . '/icu-data-locales');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function beforeCreateStub(StubbingContextInterface $context)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'Locales' => Intl::getLocaleBundle()->getLocaleNames('en'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function afterCreateStub(StubbingContextInterface $context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private function scanLocales(CompilationContextInterface $context)
|
||||||
|
{
|
||||||
|
$tempDir = sys_get_temp_dir() . '/icu-data-locales-source';
|
||||||
|
|
||||||
|
$context->getFilesystem()->remove($tempDir);
|
||||||
|
$context->getFilesystem()->mkdir($tempDir);
|
||||||
|
|
||||||
|
// Temporarily generate the resource bundles
|
||||||
|
$context->getCompiler()->compile($context->getSourceDir() . '/locales', $tempDir);
|
||||||
|
|
||||||
|
// Discover the list of supported locales, which are the names of the resource
|
||||||
|
// bundles in the "locales" directory
|
||||||
|
$locales = glob($tempDir . '/*.res');
|
||||||
|
|
||||||
|
// Remove file extension and sort
|
||||||
|
array_walk($locales, function (&$locale) { $locale = basename($locale, '.res'); });
|
||||||
|
sort($locales);
|
||||||
|
|
||||||
|
// Delete unneeded locales
|
||||||
|
foreach ($locales as $key => $locale) {
|
||||||
|
// Delete all aliases from the list
|
||||||
|
// i.e., "az_AZ" is an alias for "az_Latn_AZ"
|
||||||
|
$content = file_get_contents($context->getSourceDir() . '/locales/' . $locale . '.txt');
|
||||||
|
|
||||||
|
// The key "%%ALIAS" is not accessible through the \ResourceBundle class,
|
||||||
|
// so look in the original .txt file instead
|
||||||
|
if (strpos($content, '%%ALIAS') !== false) {
|
||||||
|
unset($locales[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete locales that have no content (i.e. only "Version" key)
|
||||||
|
$bundle = new \ResourceBundle($locale, $tempDir);
|
||||||
|
|
||||||
|
if (null === $bundle) {
|
||||||
|
throw new RuntimeException('The resource bundle for locale ' . $locale . ' could not be loaded from directory ' . $tempDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// There seems to be no other way for identifying all keys in this specific
|
||||||
|
// resource bundle
|
||||||
|
if (array_keys(iterator_to_array($bundle)) === array('Version')) {
|
||||||
|
unset($locales[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$context->getFilesystem()->remove($tempDir);
|
||||||
|
|
||||||
|
return $locales;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateTextFiles($targetDirectory, array $locales)
|
||||||
|
{
|
||||||
|
$displayLocales = array_unique(array_merge(
|
||||||
|
$this->languageBundle->getLocales(),
|
||||||
|
$this->regionBundle->getLocales()
|
||||||
|
));
|
||||||
|
|
||||||
|
$txtWriter = new TextBundleWriter();
|
||||||
|
|
||||||
|
// Generate a list of locale names in the language of each display locale
|
||||||
|
// Each locale name has the form: "Language (Script, Region, Variant1, ...)
|
||||||
|
// Script, Region and Variants are optional. If none of them is available,
|
||||||
|
// the braces are not printed.
|
||||||
|
foreach ($displayLocales as $displayLocale) {
|
||||||
|
// Don't include ICU's root resource bundle
|
||||||
|
if ('root' === $displayLocale) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$names = array();
|
||||||
|
|
||||||
|
foreach ($locales as $locale) {
|
||||||
|
// Don't include ICU's root resource bundle
|
||||||
|
if ($locale === 'root') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== ($name = $this->generateLocaleName($locale, $displayLocale))) {
|
||||||
|
$names[$locale] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no names could be generated for the current locale, skip it
|
||||||
|
if (0 === count($names)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$txtWriter->write($targetDirectory, $displayLocale, array('Locales' => $names));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateLocaleName($locale, $displayLocale)
|
||||||
|
{
|
||||||
|
$name = null;
|
||||||
|
|
||||||
|
$lang = \Locale::getPrimaryLanguage($locale);
|
||||||
|
$script = \Locale::getScript($locale);
|
||||||
|
$region = \Locale::getRegion($locale);
|
||||||
|
$variants = \Locale::getAllVariants($locale);
|
||||||
|
|
||||||
|
// Currently the only available variant is POSIX, which we don't want
|
||||||
|
// to include in the list
|
||||||
|
if (count($variants) > 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some languages are translated together with their region,
|
||||||
|
// i.e. "en_GB" is translated as "British English"
|
||||||
|
// we don't include these languages though because they mess up
|
||||||
|
// the name sorting
|
||||||
|
// $name = $this->langBundle->getLanguageName($displayLocale, $lang, $region);
|
||||||
|
|
||||||
|
// Some languages are simply not translated
|
||||||
|
// Example: "az" (Azerbaijani) has no translation in "af" (Afrikaans)
|
||||||
|
if (null === ($name = $this->languageBundle->getLanguageName($displayLocale, $lang))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "as" (Assamese) has no "Variants" block
|
||||||
|
//if (!$langBundle->get('Variants')) {
|
||||||
|
// continue;
|
||||||
|
//}
|
||||||
|
|
||||||
|
$extras = array();
|
||||||
|
|
||||||
|
// Discover the name of the script part of the locale
|
||||||
|
// i.e. in zh_Hans_MO, "Hans" is the script
|
||||||
|
if ($script) {
|
||||||
|
// Some scripts are not translated into every language
|
||||||
|
if (null === ($scriptName = $this->languageBundle->getScriptName($displayLocale, $script, $lang))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$extras[] = $scriptName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discover the name of the region part of the locale
|
||||||
|
// i.e. in de_AT, "AT" is the region
|
||||||
|
if ($region) {
|
||||||
|
// Some regions are not translated into every language
|
||||||
|
if (null === ($regionName = $this->regionBundle->getCountryName($displayLocale, $region))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$extras[] = $regionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($extras) > 0) {
|
||||||
|
// Remove any existing extras
|
||||||
|
// For example, in German, zh_Hans is "Chinesisch (vereinfacht)".
|
||||||
|
// The latter is the script part which is already included in the
|
||||||
|
// extras and will be appended again with the other extras.
|
||||||
|
if (preg_match('/^(.+)\s+\([^\)]+\)$/', $name, $matches)) {
|
||||||
|
$name = $matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$name .= ' ('.implode(', ', $extras).')';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Intl;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rule for compiling the region bundle.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class RegionBundleTransformationRule implements TransformationRuleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getBundleName()
|
||||||
|
{
|
||||||
|
return 'region';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function beforeCompile(CompilationContextInterface $context)
|
||||||
|
{
|
||||||
|
// The region data is contained in the locales bundle in ICU <= 4.2
|
||||||
|
if (version_compare($context->getIcuVersion(), '4.2', '<=')) {
|
||||||
|
return $context->getSourceDir() . '/locales';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $context->getSourceDir() . '/region';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function afterCompile(CompilationContextInterface $context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function beforeCreateStub(StubbingContextInterface $context)
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'Countries' => Intl::getRegionBundle()->getCountryNames('en'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function afterCreateStub(StubbingContextInterface $context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains instruction for compiling a resource bundle.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface TransformationRuleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the name of the compiled resource bundle.
|
||||||
|
*
|
||||||
|
* @return string The name of the bundle.
|
||||||
|
*/
|
||||||
|
public function getBundleName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs instructions to be executed before compiling the sources of the
|
||||||
|
* resource bundle.
|
||||||
|
*
|
||||||
|
* @param CompilationContextInterface $context The contextual information of
|
||||||
|
* the compilation.
|
||||||
|
*
|
||||||
|
* @return string[] The source directories/files of the bundle.
|
||||||
|
*/
|
||||||
|
public function beforeCompile(CompilationContextInterface $context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs instructions to be executed after compiling the sources of the
|
||||||
|
* resource bundle.
|
||||||
|
*
|
||||||
|
* @param CompilationContextInterface $context The contextual information of
|
||||||
|
* the compilation.
|
||||||
|
*/
|
||||||
|
public function afterCompile(CompilationContextInterface $context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs instructions to be executed before creating the stub version of the
|
||||||
|
* resource bundle.
|
||||||
|
*
|
||||||
|
* @param StubbingContextInterface $context The contextual information of
|
||||||
|
* the compilation.
|
||||||
|
*
|
||||||
|
* @return mixed The data to include in the stub version.
|
||||||
|
*/
|
||||||
|
public function beforeCreateStub(StubbingContextInterface $context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs instructions to be executed after creating the stub version of the
|
||||||
|
* resource bundle.
|
||||||
|
*
|
||||||
|
* @param StubbingContextInterface $context The contextual information of
|
||||||
|
* the compilation.
|
||||||
|
*/
|
||||||
|
public function afterCreateStub(StubbingContextInterface $context);
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Transformer;
|
||||||
|
|
||||||
|
use Symfony\Component\Filesystem\Filesystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class StubbingContext implements StubbingContextInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $binaryDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $stubDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Filesystem
|
||||||
|
*/
|
||||||
|
private $filesystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $icuVersion;
|
||||||
|
|
||||||
|
public function __construct($binaryDir, $stubDir, Filesystem $filesystem, $icuVersion)
|
||||||
|
{
|
||||||
|
$this->binaryDir = $binaryDir;
|
||||||
|
$this->stubDir = $stubDir;
|
||||||
|
$this->filesystem = $filesystem;
|
||||||
|
$this->icuVersion = $icuVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getBinaryDir()
|
||||||
|
{
|
||||||
|
return $this->binaryDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getStubDir()
|
||||||
|
{
|
||||||
|
return $this->stubDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getFilesystem()
|
||||||
|
{
|
||||||
|
return $this->filesystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getIcuVersion()
|
||||||
|
{
|
||||||
|
return $this->icuVersion;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Transformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface StubbingContextInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the directory where the binary resource bundles are stored.
|
||||||
|
*
|
||||||
|
* @return string An absolute path to a directory.
|
||||||
|
*/
|
||||||
|
public function getBinaryDir();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the directory where the stub resource bundles are stored.
|
||||||
|
*
|
||||||
|
* @return string An absolute path to a directory.
|
||||||
|
*/
|
||||||
|
public function getStubDir();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a tool for manipulating the filesystem.
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\Filesystem\Filesystem The filesystem manipulator.
|
||||||
|
*/
|
||||||
|
public function getFilesystem();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ICU version of the bundles being converted.
|
||||||
|
*
|
||||||
|
* @return string The ICU version string.
|
||||||
|
*/
|
||||||
|
public function getIcuVersion();
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Util;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\BadMethodCallException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Work-around for a bug in PHP's \ResourceBundle implementation.
|
||||||
|
*
|
||||||
|
* More information can be found on https://bugs.php.net/bug.php?id=64356.
|
||||||
|
* This class can be removed once that bug is fixed.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class ArrayAccessibleResourceBundle implements \ArrayAccess, \IteratorAggregate, \Countable
|
||||||
|
{
|
||||||
|
private $bundleImpl;
|
||||||
|
|
||||||
|
public function __construct(\ResourceBundle $bundleImpl)
|
||||||
|
{
|
||||||
|
$this->bundleImpl = $bundleImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get($offset, $fallback = null)
|
||||||
|
{
|
||||||
|
$value = $this->bundleImpl->get($offset, $fallback);
|
||||||
|
|
||||||
|
return $value instanceof \ResourceBundle ? new static($value) : $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offsetExists($offset)
|
||||||
|
{
|
||||||
|
return null !== $this->bundleImpl[$offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offsetGet($offset)
|
||||||
|
{
|
||||||
|
return $this->get($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offsetSet($offset, $value)
|
||||||
|
{
|
||||||
|
throw new BadMethodCallException('Resource bundles cannot be modified.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offsetUnset($offset)
|
||||||
|
{
|
||||||
|
throw new BadMethodCallException('Resource bundles cannot be modified.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return $this->bundleImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return $this->bundleImpl->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getErrorCode()
|
||||||
|
{
|
||||||
|
return $this->bundleImpl->getErrorCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getErrorMessage()
|
||||||
|
{
|
||||||
|
return $this->bundleImpl->getErrorMessage();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class RecursiveArrayAccess
|
||||||
|
{
|
||||||
|
public static function get($array, array $indices)
|
||||||
|
{
|
||||||
|
foreach ($indices as $index) {
|
||||||
|
if (!$array instanceof \ArrayAccess && !is_array($array)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$array = $array[$index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function __construct() {}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Util;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Exception\OutOfBoundsException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a ring buffer.
|
||||||
|
*
|
||||||
|
* A ring buffer is an array-like structure with a fixed size. If the buffer
|
||||||
|
* is full, the next written element overwrites the first bucket in the buffer,
|
||||||
|
* then the second and so on.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class RingBuffer implements \ArrayAccess
|
||||||
|
{
|
||||||
|
private $values = array();
|
||||||
|
|
||||||
|
private $indices = array();
|
||||||
|
|
||||||
|
private $cursor = 0;
|
||||||
|
|
||||||
|
private $size;
|
||||||
|
|
||||||
|
public function __construct($size)
|
||||||
|
{
|
||||||
|
$this->size = $size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function offsetExists($key)
|
||||||
|
{
|
||||||
|
return isset($this->indices[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function offsetGet($key)
|
||||||
|
{
|
||||||
|
if (!isset($this->indices[$key])) {
|
||||||
|
throw new OutOfBoundsException(sprintf(
|
||||||
|
'The index "%s" does not exist.',
|
||||||
|
$key
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->values[$this->indices[$key]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function offsetSet($key, $value)
|
||||||
|
{
|
||||||
|
if (false !== ($keyToRemove = array_search($this->cursor, $this->indices))) {
|
||||||
|
unset($this->indices[$keyToRemove]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->values[$this->cursor] = $value;
|
||||||
|
$this->indices[$key] = $this->cursor;
|
||||||
|
|
||||||
|
$this->cursor = ($this->cursor + 1) % $this->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function offsetUnset($key)
|
||||||
|
{
|
||||||
|
if (isset($this->indices[$key])) {
|
||||||
|
$this->values[$this->indices[$key]] = null;
|
||||||
|
unset($this->indices[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes resource bundle files.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
interface BundleWriterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Writes data to a resource bundle.
|
||||||
|
*
|
||||||
|
* @param string $path The path to the resource bundle.
|
||||||
|
* @param string $locale The locale to (over-)write.
|
||||||
|
* @param mixed $data The data to write.
|
||||||
|
*/
|
||||||
|
public function write($path, $locale, $data);
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes .php resource bundles.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class PhpBundleWriter implements BundleWriterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
function write($path, $locale, $data)
|
||||||
|
{
|
||||||
|
$template = <<<TEMPLATE
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return %s;
|
||||||
|
|
||||||
|
TEMPLATE;
|
||||||
|
|
||||||
|
$data = var_export($data, true);
|
||||||
|
$data = preg_replace('/array \(/', 'array(', $data);
|
||||||
|
$data = preg_replace('/\n {1,10}array\(/', 'array(', $data);
|
||||||
|
$data = preg_replace('/ /', ' ', $data);
|
||||||
|
$data = sprintf($template, $data);
|
||||||
|
|
||||||
|
file_put_contents($path.'/'.$locale.'.php', $data);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,202 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\ResourceBundle\Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes .txt resource bundles.
|
||||||
|
*
|
||||||
|
* The resulting files can be converted to binary .res files using the
|
||||||
|
* {@link \Symfony\Component\Intl\ResourceBundle\Transformer\BundleCompiler}.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt
|
||||||
|
*/
|
||||||
|
class TextBundleWriter implements BundleWriterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function write($path, $locale, $data)
|
||||||
|
{
|
||||||
|
$file = fopen($path.'/'.$locale.'.txt', 'w');
|
||||||
|
|
||||||
|
$this->writeResourceBundle($file, $locale, $data);
|
||||||
|
|
||||||
|
fclose($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a "resourceBundle" node.
|
||||||
|
*
|
||||||
|
* @param resource $file The file handle to write to.
|
||||||
|
* @param string $bundleName The name of the bundle.
|
||||||
|
* @param mixed $value The value of the node.
|
||||||
|
*
|
||||||
|
* @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt
|
||||||
|
*/
|
||||||
|
private function writeResourceBundle($file, $bundleName, $value)
|
||||||
|
{
|
||||||
|
fwrite($file, $bundleName);
|
||||||
|
|
||||||
|
$this->writeTable($file, $value, 0);
|
||||||
|
|
||||||
|
fwrite($file, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a "resource" node.
|
||||||
|
*
|
||||||
|
* @param resource $file The file handle to write to.
|
||||||
|
* @param mixed $value The value of the node.
|
||||||
|
* @param integer $indentation The number of levels to indent.
|
||||||
|
* @param Boolean $requireBraces Whether to require braces to be printed
|
||||||
|
* around the value.
|
||||||
|
*
|
||||||
|
* @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt
|
||||||
|
*/
|
||||||
|
private function writeResource($file, $value, $indentation, $requireBraces = true)
|
||||||
|
{
|
||||||
|
if (is_int($value)) {
|
||||||
|
$this->writeInteger($file, $value);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value)) {
|
||||||
|
if (count($value) === count(array_filter($value, 'is_int'))) {
|
||||||
|
$this->writeIntVector($file, $value, $indentation);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$keys = array_keys($value);
|
||||||
|
|
||||||
|
if (count($keys) === count(array_filter($keys, 'is_int'))) {
|
||||||
|
$this->writeArray($file, $value, $indentation);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writeTable($file, $value, $indentation);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_bool($value)) {
|
||||||
|
$value = $value ? 'true' : 'false';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writeString($file, (string) $value, $requireBraces);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an "integer" node.
|
||||||
|
*
|
||||||
|
* @param resource $file The file handle to write to.
|
||||||
|
* @param integer $value The value of the node.
|
||||||
|
*
|
||||||
|
* @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt
|
||||||
|
*/
|
||||||
|
private function writeInteger($file, $value)
|
||||||
|
{
|
||||||
|
fprintf($file, ':int{%d}', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an "intvector" node.
|
||||||
|
*
|
||||||
|
* @param resource $file The file handle to write to.
|
||||||
|
* @param array $value The value of the node.
|
||||||
|
* @param integer $indentation The number of levels to indent.
|
||||||
|
*
|
||||||
|
* @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt
|
||||||
|
*/
|
||||||
|
private function writeIntVector($file, array $value, $indentation)
|
||||||
|
{
|
||||||
|
fwrite($file, ":intvector{\n");
|
||||||
|
|
||||||
|
foreach ($value as $int) {
|
||||||
|
fprintf($file, "%s%d,\n", str_repeat(' ', $indentation + 1), $int);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf($file, "%s}", str_repeat(' ', $indentation));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a "string" node.
|
||||||
|
*
|
||||||
|
* @param resource $file The file handle to write to.
|
||||||
|
* @param string $value The value of the node.
|
||||||
|
* @param Boolean $requireBraces Whether to require braces to be printed
|
||||||
|
* around the value.
|
||||||
|
*
|
||||||
|
* @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt
|
||||||
|
*/
|
||||||
|
private function writeString($file, $value, $requireBraces = true)
|
||||||
|
{
|
||||||
|
if ($requireBraces) {
|
||||||
|
fprintf($file, '{"%s"}', $value);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf($file, '"%s"', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an "array" node.
|
||||||
|
*
|
||||||
|
* @param resource $file The file handle to write to.
|
||||||
|
* @param array $value The value of the node.
|
||||||
|
* @param integer $indentation The number of levels to indent.
|
||||||
|
*
|
||||||
|
* @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt
|
||||||
|
*/
|
||||||
|
private function writeArray($file, array $value, $indentation)
|
||||||
|
{
|
||||||
|
fwrite($file, "{\n");
|
||||||
|
|
||||||
|
foreach ($value as $entry) {
|
||||||
|
fwrite($file, str_repeat(' ', $indentation + 1));
|
||||||
|
|
||||||
|
$this->writeResource($file, $entry, $indentation + 1, false);
|
||||||
|
|
||||||
|
fwrite($file, ",\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf($file, '%s}', str_repeat(' ', $indentation));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a "table" node.
|
||||||
|
*
|
||||||
|
* @param resource $file The file handle to write to.
|
||||||
|
* @param array $value The value of the node.
|
||||||
|
* @param integer $indentation The number of levels to indent.
|
||||||
|
*/
|
||||||
|
private function writeTable($file, array $value, $indentation)
|
||||||
|
{
|
||||||
|
fwrite($file, "{\n");
|
||||||
|
|
||||||
|
foreach ($value as $key => $entry) {
|
||||||
|
fwrite($file, str_repeat(' ', $indentation + 1));
|
||||||
|
fwrite($file, $key);
|
||||||
|
|
||||||
|
$this->writeResource($file, $entry, $indentation + 1);
|
||||||
|
|
||||||
|
fwrite($file, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf($file, '%s}', str_repeat(' ', $indentation));
|
||||||
|
}
|
||||||
|
}
|
69
src/Symfony/Component/Intl/Resources/bin/common.php
Normal file
69
src/Symfony/Component/Intl/Resources/bin/common.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
define('LINE_WIDTH', 75);
|
||||||
|
|
||||||
|
define('LINE', str_repeat('-', LINE_WIDTH) . "\n");
|
||||||
|
|
||||||
|
function bailout($message)
|
||||||
|
{
|
||||||
|
echo wordwrap($message, LINE_WIDTH) . " Aborting.\n";
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function strip_minor_versions($version)
|
||||||
|
{
|
||||||
|
preg_match('/^(?P<version>[0-9]\.[0-9]|[0-9]{2,})/', $version, $matches);
|
||||||
|
|
||||||
|
return $matches['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function centered($text)
|
||||||
|
{
|
||||||
|
$padding = (int) ((LINE_WIDTH - strlen($text))/2);
|
||||||
|
|
||||||
|
return str_repeat(' ', $padding) . $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cd($dir)
|
||||||
|
{
|
||||||
|
if (false === chdir($dir)) {
|
||||||
|
bailout("Could not switch to directory $dir.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function run($command)
|
||||||
|
{
|
||||||
|
exec($command, $output, $status);
|
||||||
|
|
||||||
|
if (0 !== $status) {
|
||||||
|
$output = implode("\n", $output);
|
||||||
|
echo "Error:\n" . LINE . "$output\n" . LINE;
|
||||||
|
|
||||||
|
bailout("\"$command\" failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_icu_version_from_genrb($genrb)
|
||||||
|
{
|
||||||
|
exec($genrb . ' --version 2>&1', $output, $status);
|
||||||
|
|
||||||
|
if (0 !== $status) {
|
||||||
|
bailout($genrb . ' failed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preg_match('/ICU version ([\d\.]+)/', implode('', $output), $matches)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $matches[1];
|
||||||
|
}
|
18
src/Symfony/Component/Intl/Resources/bin/icu-version.php
Normal file
18
src/Symfony/Component/Intl/Resources/bin/icu-version.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Intl;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/common.php';
|
||||||
|
require_once __DIR__ . '/autoload.php';
|
||||||
|
|
||||||
|
echo "ICU version: ";
|
||||||
|
echo Intl::getIcuVersion() . "\n";
|
@ -1,9 +1,9 @@
|
|||||||
; ICU data source URLs
|
; ICU data source URLs
|
||||||
; We use always the latest release of a major version.
|
; We use always the latest release of a major version.
|
||||||
4.0 = http://source.icu-project.org/repos/icu/icu/tags/release-4-0-1/source/data
|
4.0 = http://source.icu-project.org/repos/icu/icu/tags/release-4-0-1/source
|
||||||
4.2 = http://source.icu-project.org/repos/icu/icu/tags/release-4-2-1/source/data
|
4.2 = http://source.icu-project.org/repos/icu/icu/tags/release-4-2-1/source
|
||||||
4.4 = http://source.icu-project.org/repos/icu/icu/tags/release-4-4-2/source/data
|
4.4 = http://source.icu-project.org/repos/icu/icu/tags/release-4-4-2/source
|
||||||
4.6 = http://source.icu-project.org/repos/icu/icu/tags/release-4-6-1/source/data
|
4.6 = http://source.icu-project.org/repos/icu/icu/tags/release-4-6-1/source
|
||||||
4.8 = http://source.icu-project.org/repos/icu/icu/tags/release-4-8-1-1/source/data
|
4.8 = http://source.icu-project.org/repos/icu/icu/tags/release-4-8-1-1/source
|
||||||
49 = http://source.icu-project.org/repos/icu/icu/tags/release-49-1-2/source/data
|
49 = http://source.icu-project.org/repos/icu/icu/tags/release-49-1-2/source
|
||||||
50 = http://source.icu-project.org/repos/icu/icu/tags/release-50-1/source/data
|
50 = http://source.icu-project.org/repos/icu/icu/tags/release-50-1/source
|
@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Symfony\Component\Icu\IcuData;
|
||||||
|
use Symfony\Component\Intl\Intl;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Compiler\BundleCompiler;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\BundleTransformer;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContext;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\CurrencyBundleTransformationRule;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\LanguageBundleTransformationRule;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\LocaleBundleTransformationRule;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\RegionBundleTransformationRule;
|
||||||
|
use Symfony\Component\Intl\Util\SvnRepository;
|
||||||
|
use Symfony\Component\Filesystem\Filesystem;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/common.php';
|
||||||
|
require_once __DIR__ . '/autoload.php';
|
||||||
|
|
||||||
|
if (1 !== $GLOBALS['argc']) {
|
||||||
|
bailout(<<<MESSAGE
|
||||||
|
Usage: php update-icu-component.php
|
||||||
|
|
||||||
|
Updates the ICU data for Symfony2 to the latest version of the ICU version
|
||||||
|
included in the intl extension. For example, if your intl extension includes
|
||||||
|
ICU 4.8, the script will download the latest data available for ICU 4.8.
|
||||||
|
|
||||||
|
For running this script, the intl extension must be loaded and all vendors
|
||||||
|
must have been installed through composer:
|
||||||
|
|
||||||
|
composer install --dev
|
||||||
|
|
||||||
|
MESSAGE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo LINE;
|
||||||
|
echo centered("ICU Resource Bundle Compilation") . "\n";
|
||||||
|
echo LINE;
|
||||||
|
|
||||||
|
if (!Intl::isExtensionLoaded()) {
|
||||||
|
bailout('The intl extension for PHP is not installed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!class_exists('\Symfony\Component\Icu\IcuData')) {
|
||||||
|
bailout('You must run "composer update --dev" before running this script.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$icuVersionInPhp = Intl::getIcuVersion();
|
||||||
|
|
||||||
|
echo "Found intl extension with ICU version $icuVersionInPhp.\n";
|
||||||
|
|
||||||
|
$shortIcuVersion = strip_minor_versions($icuVersionInPhp);
|
||||||
|
$urls = parse_ini_file(__DIR__ . '/icu.ini');
|
||||||
|
|
||||||
|
if (!isset($urls[$shortIcuVersion])) {
|
||||||
|
bailout('The version ' . $shortIcuVersion . ' is not available in the icu.ini file.');
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "icu.ini parsed. Available versions:\n";
|
||||||
|
|
||||||
|
foreach ($urls as $urlVersion => $url) {
|
||||||
|
echo " $urlVersion\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Starting SVN checkout for version $shortIcuVersion. This may take a while...\n";
|
||||||
|
|
||||||
|
$svn = SvnRepository::download($urls[$shortIcuVersion], $shortIcuVersion);
|
||||||
|
|
||||||
|
echo "SVN checkout to {$svn->getPath()} complete.\n";
|
||||||
|
|
||||||
|
// Always build genrb so that we can determine the ICU version of the
|
||||||
|
// download by running genrb --version
|
||||||
|
echo "Building genrb.\n";
|
||||||
|
|
||||||
|
cd($svn->getPath());
|
||||||
|
|
||||||
|
echo "Running make clean...\n";
|
||||||
|
|
||||||
|
run('make clean');
|
||||||
|
|
||||||
|
echo "Running configure...\n";
|
||||||
|
|
||||||
|
run('./configure 2>&1');
|
||||||
|
|
||||||
|
cd($svn->getPath() . '/tools');
|
||||||
|
|
||||||
|
echo "Running make...\n";
|
||||||
|
|
||||||
|
run('make 2>&1');
|
||||||
|
|
||||||
|
$genrb = $svn->getPath() . '/bin/genrb';
|
||||||
|
|
||||||
|
echo "Using $genrb.\n";
|
||||||
|
|
||||||
|
$icuVersionInDownload = get_icu_version_from_genrb($genrb);
|
||||||
|
|
||||||
|
echo "Preparing resource bundle compilation (version $icuVersionInDownload)...\n";
|
||||||
|
|
||||||
|
$context = new CompilationContext(
|
||||||
|
$svn->getPath() . '/data',
|
||||||
|
IcuData::getResourceDirectory(),
|
||||||
|
new Filesystem(),
|
||||||
|
new BundleCompiler($genrb),
|
||||||
|
$icuVersionInDownload
|
||||||
|
);
|
||||||
|
|
||||||
|
$transformer = new BundleTransformer();
|
||||||
|
$transformer->addRule(new LanguageBundleTransformationRule());
|
||||||
|
$transformer->addRule(new RegionBundleTransformationRule());
|
||||||
|
$transformer->addRule(new CurrencyBundleTransformationRule());
|
||||||
|
$transformer->addRule(new LocaleBundleTransformationRule());
|
||||||
|
|
||||||
|
echo "Starting resource bundle compilation. This may take a while...\n";
|
||||||
|
|
||||||
|
$transformer->compileBundles($context);
|
||||||
|
|
||||||
|
echo "Resource bundle compilation complete.\n";
|
||||||
|
|
||||||
|
$svnInfo = <<<SVN_INFO
|
||||||
|
SVN information
|
||||||
|
===============
|
||||||
|
|
||||||
|
URL: {$svn->getUrl()}
|
||||||
|
Revision: {$svn->getLastCommit()->getRevision()}
|
||||||
|
Author: {$svn->getLastCommit()->getAuthor()}
|
||||||
|
Date: {$svn->getLastCommit()->getDate()}
|
||||||
|
|
||||||
|
SVN_INFO;
|
||||||
|
|
||||||
|
$svnInfoFile = $context->getBinaryDir() . '/svn-info.txt';
|
||||||
|
|
||||||
|
file_put_contents($svnInfoFile, $svnInfo);
|
||||||
|
|
||||||
|
echo "Wrote $svnInfoFile.\n";
|
||||||
|
|
||||||
|
$versionFile = $context->getBinaryDir() . '/version.txt';
|
||||||
|
|
||||||
|
file_put_contents($versionFile, "$icuVersionInDownload\n");
|
||||||
|
|
||||||
|
echo "Wrote $versionFile.\n";
|
||||||
|
|
||||||
|
echo "Done.\n";
|
95
src/Symfony/Component/Intl/Resources/bin/update-stubs.php
Normal file
95
src/Symfony/Component/Intl/Resources/bin/update-stubs.php
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Symfony\Component\Filesystem\Filesystem;
|
||||||
|
use Symfony\Component\Icu\IcuData;
|
||||||
|
use Symfony\Component\Intl\Intl;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\BundleTransformer;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\CurrencyBundleTransformationRule;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\LanguageBundleTransformationRule;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\LocaleBundleTransformationRule;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\RegionBundleTransformationRule;
|
||||||
|
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContext;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/common.php';
|
||||||
|
require_once __DIR__ . '/autoload.php';
|
||||||
|
|
||||||
|
if (1 !== $GLOBALS['argc']) {
|
||||||
|
bailout(<<<MESSAGE
|
||||||
|
Usage: php update-stubs.php
|
||||||
|
|
||||||
|
Creates resource bundle stubs from the resource bundles in the Icu component.
|
||||||
|
|
||||||
|
For running this script, the intl extension must be loaded and all vendors
|
||||||
|
must have been installed through composer:
|
||||||
|
|
||||||
|
composer install --dev
|
||||||
|
|
||||||
|
MESSAGE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo LINE;
|
||||||
|
echo centered("ICU Resource Bundle Stub Creation") . "\n";
|
||||||
|
echo LINE;
|
||||||
|
|
||||||
|
if (!Intl::isExtensionLoaded()) {
|
||||||
|
bailout('The intl extension for PHP is not installed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!class_exists('\Symfony\Component\Icu\IcuData')) {
|
||||||
|
bailout('You must run "composer update --dev" before running this script.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$shortIcuVersionInPhp = strip_minor_versions(Intl::getIcuVersion());
|
||||||
|
$shortIcuVersionInIntlComponent = strip_minor_versions(Intl::getStubIcuVersion());
|
||||||
|
$shortIcuVersionInIcuComponent = strip_minor_versions(IcuData::getVersion());
|
||||||
|
|
||||||
|
if ($shortIcuVersionInPhp !== $shortIcuVersionInIcuComponent) {
|
||||||
|
bailout("The ICU version of the component ($shortIcuVersionInIcuComponent) does not match the ICU version in the intl extension ($shortIcuVersionInPhp).");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($shortIcuVersionInIntlComponent !== $shortIcuVersionInIcuComponent) {
|
||||||
|
bailout("The ICU version of the component ($shortIcuVersionInIcuComponent) does not match the ICU version of the stub classes in the Intl component ($shortIcuVersionInIntlComponent).");
|
||||||
|
}
|
||||||
|
|
||||||
|
$icuVersionInIcuComponent = IcuData::getVersion();
|
||||||
|
|
||||||
|
echo "Compiling stubs for ICU version $icuVersionInIcuComponent.";
|
||||||
|
|
||||||
|
echo "Preparing stub creation...\n";
|
||||||
|
|
||||||
|
$context = new StubbingContext(
|
||||||
|
IcuData::getResourceDirectory(),
|
||||||
|
realpath(__DIR__ . '/../data'),
|
||||||
|
new Filesystem(),
|
||||||
|
$icuVersionInIcuComponent
|
||||||
|
);
|
||||||
|
|
||||||
|
$transformer = new BundleTransformer();
|
||||||
|
$transformer->addRule(new LanguageBundleTransformationRule());
|
||||||
|
$transformer->addRule(new RegionBundleTransformationRule());
|
||||||
|
$transformer->addRule(new CurrencyBundleTransformationRule());
|
||||||
|
$transformer->addRule(new LocaleBundleTransformationRule());
|
||||||
|
|
||||||
|
echo "Starting stub creation...\n";
|
||||||
|
|
||||||
|
$transformer->createStubs($context);
|
||||||
|
|
||||||
|
echo "Stub creation complete.\n";
|
||||||
|
|
||||||
|
$versionFile = $context->getStubDir() . '/version.txt';
|
||||||
|
|
||||||
|
file_put_contents($versionFile, "$icuVersionInIcuComponent\n");
|
||||||
|
|
||||||
|
echo "Wrote $versionFile.\n";
|
||||||
|
|
||||||
|
echo "Done.\n";
|
1773
src/Symfony/Component/Intl/Resources/data/curr/en.php
Normal file
1773
src/Symfony/Component/Intl/Resources/data/curr/en.php
Normal file
File diff suppressed because it is too large
Load Diff
707
src/Symfony/Component/Intl/Resources/data/lang/en.php
Normal file
707
src/Symfony/Component/Intl/Resources/data/lang/en.php
Normal file
@ -0,0 +1,707 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Languages' => array(
|
||||||
|
'ab' => 'Abkhazian',
|
||||||
|
'ace' => 'Achinese',
|
||||||
|
'ach' => 'Acoli',
|
||||||
|
'ada' => 'Adangme',
|
||||||
|
'ady' => 'Adyghe',
|
||||||
|
'aa' => 'Afar',
|
||||||
|
'afh' => 'Afrihili',
|
||||||
|
'af' => 'Afrikaans',
|
||||||
|
'afa' => 'Afro-Asiatic Language',
|
||||||
|
'agq' => 'Aghem',
|
||||||
|
'ain' => 'Ainu',
|
||||||
|
'ak' => 'Akan',
|
||||||
|
'akk' => 'Akkadian',
|
||||||
|
'sq' => 'Albanian',
|
||||||
|
'ale' => 'Aleut',
|
||||||
|
'alg' => 'Algonquian Language',
|
||||||
|
'tut' => 'Altaic Language',
|
||||||
|
'am' => 'Amharic',
|
||||||
|
'egy' => 'Ancient Egyptian',
|
||||||
|
'grc' => 'Ancient Greek',
|
||||||
|
'anp' => 'Angika',
|
||||||
|
'apa' => 'Apache Language',
|
||||||
|
'ar' => 'Arabic',
|
||||||
|
'an' => 'Aragonese',
|
||||||
|
'arc' => 'Aramaic',
|
||||||
|
'arp' => 'Arapaho',
|
||||||
|
'arn' => 'Araucanian',
|
||||||
|
'arw' => 'Arawak',
|
||||||
|
'hy' => 'Armenian',
|
||||||
|
'rup' => 'Aromanian',
|
||||||
|
'art' => 'Artificial Language',
|
||||||
|
'as' => 'Assamese',
|
||||||
|
'ast' => 'Asturian',
|
||||||
|
'asa' => 'Asu',
|
||||||
|
'ath' => 'Athapascan Language',
|
||||||
|
'cch' => 'Atsam',
|
||||||
|
'en_AU' => 'Australian English',
|
||||||
|
'aus' => 'Australian Language',
|
||||||
|
'de_AT' => 'Austrian German',
|
||||||
|
'map' => 'Austronesian Language',
|
||||||
|
'av' => 'Avaric',
|
||||||
|
'ae' => 'Avestan',
|
||||||
|
'awa' => 'Awadhi',
|
||||||
|
'ay' => 'Aymara',
|
||||||
|
'az' => 'Azerbaijani',
|
||||||
|
'ksf' => 'Bafia',
|
||||||
|
'ban' => 'Balinese',
|
||||||
|
'bat' => 'Baltic Language',
|
||||||
|
'bal' => 'Baluchi',
|
||||||
|
'bm' => 'Bambara',
|
||||||
|
'bai' => 'Bamileke Language',
|
||||||
|
'bad' => 'Banda',
|
||||||
|
'bnt' => 'Bantu',
|
||||||
|
'bas' => 'Basaa',
|
||||||
|
'ba' => 'Bashkir',
|
||||||
|
'eu' => 'Basque',
|
||||||
|
'btk' => 'Batak',
|
||||||
|
'bej' => 'Beja',
|
||||||
|
'be' => 'Belarusian',
|
||||||
|
'bem' => 'Bemba',
|
||||||
|
'bez' => 'Bena',
|
||||||
|
'bn' => 'Bengali',
|
||||||
|
'ber' => 'Berber',
|
||||||
|
'bho' => 'Bhojpuri',
|
||||||
|
'bh' => 'Bihari',
|
||||||
|
'bik' => 'Bikol',
|
||||||
|
'bin' => 'Bini',
|
||||||
|
'bi' => 'Bislama',
|
||||||
|
'byn' => 'Blin',
|
||||||
|
'zbl' => 'Blissymbols',
|
||||||
|
'brx' => 'Bodo',
|
||||||
|
'bs' => 'Bosnian',
|
||||||
|
'bra' => 'Braj',
|
||||||
|
'pt_BR' => 'Brazilian Portuguese',
|
||||||
|
'br' => 'Breton',
|
||||||
|
'en_GB' => 'British English',
|
||||||
|
'bug' => 'Buginese',
|
||||||
|
'bg' => 'Bulgarian',
|
||||||
|
'bua' => 'Buriat',
|
||||||
|
'my' => 'Burmese',
|
||||||
|
'cad' => 'Caddo',
|
||||||
|
'en_CA' => 'Canadian English',
|
||||||
|
'fr_CA' => 'Canadian French',
|
||||||
|
'yue' => 'Cantonese',
|
||||||
|
'car' => 'Carib',
|
||||||
|
'ca' => 'Catalan',
|
||||||
|
'cau' => 'Caucasian Language',
|
||||||
|
'cay' => 'Cayuga',
|
||||||
|
'ceb' => 'Cebuano',
|
||||||
|
'cel' => 'Celtic Language',
|
||||||
|
'cai' => 'Central American Indian Language',
|
||||||
|
'tzm' => 'Central Morocco Tamazight',
|
||||||
|
'chg' => 'Chagatai',
|
||||||
|
'cmc' => 'Chamic Language',
|
||||||
|
'ch' => 'Chamorro',
|
||||||
|
'ce' => 'Chechen',
|
||||||
|
'chr' => 'Cherokee',
|
||||||
|
'chy' => 'Cheyenne',
|
||||||
|
'chb' => 'Chibcha',
|
||||||
|
'cgg' => 'Chiga',
|
||||||
|
'zh' => 'Chinese',
|
||||||
|
'chn' => 'Chinook Jargon',
|
||||||
|
'chp' => 'Chipewyan',
|
||||||
|
'cho' => 'Choctaw',
|
||||||
|
'cu' => 'Church Slavic',
|
||||||
|
'chk' => 'Chuukese',
|
||||||
|
'cv' => 'Chuvash',
|
||||||
|
'nwc' => 'Classical Newari',
|
||||||
|
'syc' => 'Classical Syriac',
|
||||||
|
'ksh' => 'Colognian',
|
||||||
|
'swb' => 'Comorian',
|
||||||
|
'swc' => 'Congo Swahili',
|
||||||
|
'cop' => 'Coptic',
|
||||||
|
'kw' => 'Cornish',
|
||||||
|
'co' => 'Corsican',
|
||||||
|
'cr' => 'Cree',
|
||||||
|
'mus' => 'Creek',
|
||||||
|
'crp' => 'Creole or Pidgin',
|
||||||
|
'crh' => 'Crimean Turkish',
|
||||||
|
'hr' => 'Croatian',
|
||||||
|
'cus' => 'Cushitic Language',
|
||||||
|
'cs' => 'Czech',
|
||||||
|
'dak' => 'Dakota',
|
||||||
|
'da' => 'Danish',
|
||||||
|
'dar' => 'Dargwa',
|
||||||
|
'day' => 'Dayak',
|
||||||
|
'del' => 'Delaware',
|
||||||
|
'din' => 'Dinka',
|
||||||
|
'dv' => 'Divehi',
|
||||||
|
'doi' => 'Dogri',
|
||||||
|
'dgr' => 'Dogrib',
|
||||||
|
'dra' => 'Dravidian Language',
|
||||||
|
'dua' => 'Duala',
|
||||||
|
'nl' => 'Dutch',
|
||||||
|
'dyu' => 'Dyula',
|
||||||
|
'dz' => 'Dzongkha',
|
||||||
|
'frs' => 'Eastern Frisian',
|
||||||
|
'efi' => 'Efik',
|
||||||
|
'eka' => 'Ekajuk',
|
||||||
|
'elx' => 'Elamite',
|
||||||
|
'ebu' => 'Embu',
|
||||||
|
'en' => 'English',
|
||||||
|
'cpe' => 'English-based Creole or Pidgin',
|
||||||
|
'myv' => 'Erzya',
|
||||||
|
'eo' => 'Esperanto',
|
||||||
|
'et' => 'Estonian',
|
||||||
|
'ee' => 'Ewe',
|
||||||
|
'ewo' => 'Ewondo',
|
||||||
|
'fan' => 'Fang',
|
||||||
|
'fat' => 'Fanti',
|
||||||
|
'fo' => 'Faroese',
|
||||||
|
'fj' => 'Fijian',
|
||||||
|
'fil' => 'Filipino',
|
||||||
|
'fi' => 'Finnish',
|
||||||
|
'fiu' => 'Finno-Ugrian Language',
|
||||||
|
'nl_BE' => 'Flemish',
|
||||||
|
'fon' => 'Fon',
|
||||||
|
'fr' => 'French',
|
||||||
|
'cpf' => 'French-based Creole or Pidgin',
|
||||||
|
'fur' => 'Friulian',
|
||||||
|
'ff' => 'Fulah',
|
||||||
|
'gaa' => 'Ga',
|
||||||
|
'gl' => 'Galician',
|
||||||
|
'lg' => 'Ganda',
|
||||||
|
'gay' => 'Gayo',
|
||||||
|
'gba' => 'Gbaya',
|
||||||
|
'gez' => 'Geez',
|
||||||
|
'ka' => 'Georgian',
|
||||||
|
'de' => 'German',
|
||||||
|
'gem' => 'Germanic Language',
|
||||||
|
'gil' => 'Gilbertese',
|
||||||
|
'gon' => 'Gondi',
|
||||||
|
'gor' => 'Gorontalo',
|
||||||
|
'got' => 'Gothic',
|
||||||
|
'grb' => 'Grebo',
|
||||||
|
'el' => 'Greek',
|
||||||
|
'gn' => 'Guarani',
|
||||||
|
'gu' => 'Gujarati',
|
||||||
|
'guz' => 'Gusii',
|
||||||
|
'gwi' => 'Gwichʼin',
|
||||||
|
'hai' => 'Haida',
|
||||||
|
'ht' => 'Haitian',
|
||||||
|
'ha' => 'Hausa',
|
||||||
|
'haw' => 'Hawaiian',
|
||||||
|
'he' => 'Hebrew',
|
||||||
|
'hz' => 'Herero',
|
||||||
|
'hil' => 'Hiligaynon',
|
||||||
|
'him' => 'Himachali',
|
||||||
|
'hi' => 'Hindi',
|
||||||
|
'ho' => 'Hiri Motu',
|
||||||
|
'hit' => 'Hittite',
|
||||||
|
'hmn' => 'Hmong',
|
||||||
|
'hu' => 'Hungarian',
|
||||||
|
'hup' => 'Hupa',
|
||||||
|
'iba' => 'Iban',
|
||||||
|
'pt_PT' => 'Iberian Portuguese',
|
||||||
|
'es_ES' => 'Iberian Spanish',
|
||||||
|
'is' => 'Icelandic',
|
||||||
|
'io' => 'Ido',
|
||||||
|
'ig' => 'Igbo',
|
||||||
|
'ijo' => 'Ijo',
|
||||||
|
'ilo' => 'Iloko',
|
||||||
|
'smn' => 'Inari Sami',
|
||||||
|
'inc' => 'Indic Language',
|
||||||
|
'ine' => 'Indo-European Language',
|
||||||
|
'id' => 'Indonesian',
|
||||||
|
'inh' => 'Ingush',
|
||||||
|
'ia' => 'Interlingua',
|
||||||
|
'ie' => 'Interlingue',
|
||||||
|
'iu' => 'Inuktitut',
|
||||||
|
'ik' => 'Inupiaq',
|
||||||
|
'ira' => 'Iranian Language',
|
||||||
|
'ga' => 'Irish',
|
||||||
|
'iro' => 'Iroquoian Language',
|
||||||
|
'it' => 'Italian',
|
||||||
|
'ja' => 'Japanese',
|
||||||
|
'jv' => 'Javanese',
|
||||||
|
'kaj' => 'Jju',
|
||||||
|
'dyo' => 'Jola-Fonyi',
|
||||||
|
'jrb' => 'Judeo-Arabic',
|
||||||
|
'jpr' => 'Judeo-Persian',
|
||||||
|
'kbd' => 'Kabardian',
|
||||||
|
'kea' => 'Kabuverdianu',
|
||||||
|
'kab' => 'Kabyle',
|
||||||
|
'kac' => 'Kachin',
|
||||||
|
'kl' => 'Kalaallisut',
|
||||||
|
'kln' => 'Kalenjin',
|
||||||
|
'xal' => 'Kalmyk',
|
||||||
|
'kam' => 'Kamba',
|
||||||
|
'kn' => 'Kannada',
|
||||||
|
'kr' => 'Kanuri',
|
||||||
|
'kaa' => 'Kara-Kalpak',
|
||||||
|
'krc' => 'Karachay-Balkar',
|
||||||
|
'krl' => 'Karelian',
|
||||||
|
'kar' => 'Karen',
|
||||||
|
'ks' => 'Kashmiri',
|
||||||
|
'csb' => 'Kashubian',
|
||||||
|
'kaw' => 'Kawi',
|
||||||
|
'kk' => 'Kazakh',
|
||||||
|
'kha' => 'Khasi',
|
||||||
|
'km' => 'Khmer',
|
||||||
|
'khi' => 'Khoisan Language',
|
||||||
|
'kho' => 'Khotanese',
|
||||||
|
'ki' => 'Kikuyu',
|
||||||
|
'kmb' => 'Kimbundu',
|
||||||
|
'rw' => 'Kinyarwanda',
|
||||||
|
'ky' => 'Kirghiz',
|
||||||
|
'tlh' => 'Klingon',
|
||||||
|
'kv' => 'Komi',
|
||||||
|
'kg' => 'Kongo',
|
||||||
|
'kok' => 'Konkani',
|
||||||
|
'ko' => 'Korean',
|
||||||
|
'kfo' => 'Koro',
|
||||||
|
'kos' => 'Kosraean',
|
||||||
|
'khq' => 'Koyra Chiini',
|
||||||
|
'ses' => 'Koyraboro Senni',
|
||||||
|
'kpe' => 'Kpelle',
|
||||||
|
'kro' => 'Kru',
|
||||||
|
'kj' => 'Kuanyama',
|
||||||
|
'kum' => 'Kumyk',
|
||||||
|
'ku' => 'Kurdish',
|
||||||
|
'kru' => 'Kurukh',
|
||||||
|
'kut' => 'Kutenai',
|
||||||
|
'nmg' => 'Kwasio',
|
||||||
|
'lad' => 'Ladino',
|
||||||
|
'lah' => 'Lahnda',
|
||||||
|
'lam' => 'Lamba',
|
||||||
|
'lag' => 'Langi',
|
||||||
|
'lo' => 'Lao',
|
||||||
|
'la' => 'Latin',
|
||||||
|
'es_419' => 'Latin American Spanish',
|
||||||
|
'lv' => 'Latvian',
|
||||||
|
'lez' => 'Lezghian',
|
||||||
|
'li' => 'Limburgish',
|
||||||
|
'ln' => 'Lingala',
|
||||||
|
'lt' => 'Lithuanian',
|
||||||
|
'jbo' => 'Lojban',
|
||||||
|
'nds' => 'Low German',
|
||||||
|
'dsb' => 'Lower Sorbian',
|
||||||
|
'loz' => 'Lozi',
|
||||||
|
'lu' => 'Luba-Katanga',
|
||||||
|
'lua' => 'Luba-Lulua',
|
||||||
|
'lui' => 'Luiseno',
|
||||||
|
'smj' => 'Lule Sami',
|
||||||
|
'lun' => 'Lunda',
|
||||||
|
'luo' => 'Luo',
|
||||||
|
'lus' => 'Lushai',
|
||||||
|
'lb' => 'Luxembourgish',
|
||||||
|
'luy' => 'Luyia',
|
||||||
|
'mk' => 'Macedonian',
|
||||||
|
'jmc' => 'Machame',
|
||||||
|
'mad' => 'Madurese',
|
||||||
|
'mag' => 'Magahi',
|
||||||
|
'mai' => 'Maithili',
|
||||||
|
'mak' => 'Makasar',
|
||||||
|
'mgh' => 'Makhuwa-Meetto',
|
||||||
|
'kde' => 'Makonde',
|
||||||
|
'mg' => 'Malagasy',
|
||||||
|
'ms' => 'Malay',
|
||||||
|
'ml' => 'Malayalam',
|
||||||
|
'mt' => 'Maltese',
|
||||||
|
'mnc' => 'Manchu',
|
||||||
|
'mdr' => 'Mandar',
|
||||||
|
'man' => 'Mandingo',
|
||||||
|
'mni' => 'Manipuri',
|
||||||
|
'mno' => 'Manobo Language',
|
||||||
|
'gv' => 'Manx',
|
||||||
|
'mi' => 'Maori',
|
||||||
|
'mr' => 'Marathi',
|
||||||
|
'chm' => 'Mari',
|
||||||
|
'mh' => 'Marshallese',
|
||||||
|
'mwr' => 'Marwari',
|
||||||
|
'mas' => 'Masai',
|
||||||
|
'myn' => 'Mayan Language',
|
||||||
|
'men' => 'Mende',
|
||||||
|
'mer' => 'Meru',
|
||||||
|
'mic' => 'Micmac',
|
||||||
|
'dum' => 'Middle Dutch',
|
||||||
|
'enm' => 'Middle English',
|
||||||
|
'frm' => 'Middle French',
|
||||||
|
'gmh' => 'Middle High German',
|
||||||
|
'mga' => 'Middle Irish',
|
||||||
|
'min' => 'Minangkabau',
|
||||||
|
'mwl' => 'Mirandese',
|
||||||
|
'mis' => 'Miscellaneous Language',
|
||||||
|
'moh' => 'Mohawk',
|
||||||
|
'mdf' => 'Moksha',
|
||||||
|
'mo' => 'Moldavian',
|
||||||
|
'mkh' => 'Mon-Khmer Language',
|
||||||
|
'lol' => 'Mongo',
|
||||||
|
'mn' => 'Mongolian',
|
||||||
|
'mfe' => 'Morisyen',
|
||||||
|
'mos' => 'Mossi',
|
||||||
|
'mun' => 'Munda Language',
|
||||||
|
'mua' => 'Mundang',
|
||||||
|
'nqo' => 'N’Ko',
|
||||||
|
'nah' => 'Nahuatl',
|
||||||
|
'naq' => 'Nama',
|
||||||
|
'na' => 'Nauru',
|
||||||
|
'nv' => 'Navajo',
|
||||||
|
'ng' => 'Ndonga',
|
||||||
|
'nap' => 'Neapolitan',
|
||||||
|
'ne' => 'Nepali',
|
||||||
|
'new' => 'Newari',
|
||||||
|
'nia' => 'Nias',
|
||||||
|
'nic' => 'Niger-Kordofanian Language',
|
||||||
|
'ssa' => 'Nilo-Saharan Language',
|
||||||
|
'niu' => 'Niuean',
|
||||||
|
'zxx' => 'No linguistic content',
|
||||||
|
'nog' => 'Nogai',
|
||||||
|
'nai' => 'North American Indian Language',
|
||||||
|
'nd' => 'North Ndebele',
|
||||||
|
'frr' => 'Northern Frisian',
|
||||||
|
'se' => 'Northern Sami',
|
||||||
|
'nso' => 'Northern Sotho',
|
||||||
|
'no' => 'Norwegian',
|
||||||
|
'nb' => 'Norwegian Bokmål',
|
||||||
|
'nn' => 'Norwegian Nynorsk',
|
||||||
|
'nub' => 'Nubian Language',
|
||||||
|
'nus' => 'Nuer',
|
||||||
|
'nym' => 'Nyamwezi',
|
||||||
|
'ny' => 'Nyanja',
|
||||||
|
'nyn' => 'Nyankole',
|
||||||
|
'tog' => 'Nyasa Tonga',
|
||||||
|
'nyo' => 'Nyoro',
|
||||||
|
'nzi' => 'Nzima',
|
||||||
|
'oc' => 'Occitan',
|
||||||
|
'oj' => 'Ojibwa',
|
||||||
|
'ang' => 'Old English',
|
||||||
|
'fro' => 'Old French',
|
||||||
|
'goh' => 'Old High German',
|
||||||
|
'sga' => 'Old Irish',
|
||||||
|
'non' => 'Old Norse',
|
||||||
|
'peo' => 'Old Persian',
|
||||||
|
'pro' => 'Old Provençal',
|
||||||
|
'or' => 'Oriya',
|
||||||
|
'om' => 'Oromo',
|
||||||
|
'osa' => 'Osage',
|
||||||
|
'os' => 'Ossetic',
|
||||||
|
'oto' => 'Otomian Language',
|
||||||
|
'ota' => 'Ottoman Turkish',
|
||||||
|
'pal' => 'Pahlavi',
|
||||||
|
'pau' => 'Palauan',
|
||||||
|
'pi' => 'Pali',
|
||||||
|
'pam' => 'Pampanga',
|
||||||
|
'pag' => 'Pangasinan',
|
||||||
|
'pap' => 'Papiamento',
|
||||||
|
'paa' => 'Papuan Language',
|
||||||
|
'ps' => 'Pashto',
|
||||||
|
'fa' => 'Persian',
|
||||||
|
'phi' => 'Philippine Language',
|
||||||
|
'phn' => 'Phoenician',
|
||||||
|
'pon' => 'Pohnpeian',
|
||||||
|
'pl' => 'Polish',
|
||||||
|
'pt' => 'Portuguese',
|
||||||
|
'cpp' => 'Portuguese-based Creole or Pidgin',
|
||||||
|
'pra' => 'Prakrit Language',
|
||||||
|
'pa' => 'Punjabi',
|
||||||
|
'qu' => 'Quechua',
|
||||||
|
'raj' => 'Rajasthani',
|
||||||
|
'rap' => 'Rapanui',
|
||||||
|
'rar' => 'Rarotongan',
|
||||||
|
'roa' => 'Romance Language',
|
||||||
|
'ro' => 'Romanian',
|
||||||
|
'rm' => 'Romansh',
|
||||||
|
'rom' => 'Romany',
|
||||||
|
'rof' => 'Rombo',
|
||||||
|
'root' => 'Root',
|
||||||
|
'rn' => 'Rundi',
|
||||||
|
'ru' => 'Russian',
|
||||||
|
'rwk' => 'Rwa',
|
||||||
|
'ssy' => 'Saho',
|
||||||
|
'sah' => 'Sakha',
|
||||||
|
'sal' => 'Salishan Language',
|
||||||
|
'sam' => 'Samaritan Aramaic',
|
||||||
|
'saq' => 'Samburu',
|
||||||
|
'smi' => 'Sami Language',
|
||||||
|
'sm' => 'Samoan',
|
||||||
|
'sad' => 'Sandawe',
|
||||||
|
'sg' => 'Sango',
|
||||||
|
'sbp' => 'Sangu',
|
||||||
|
'sa' => 'Sanskrit',
|
||||||
|
'sat' => 'Santali',
|
||||||
|
'sc' => 'Sardinian',
|
||||||
|
'sas' => 'Sasak',
|
||||||
|
'sco' => 'Scots',
|
||||||
|
'gd' => 'Scottish Gaelic',
|
||||||
|
'sel' => 'Selkup',
|
||||||
|
'sem' => 'Semitic Language',
|
||||||
|
'seh' => 'Sena',
|
||||||
|
'see' => 'Seneca',
|
||||||
|
'sr' => 'Serbian',
|
||||||
|
'sh' => 'Serbo-Croatian',
|
||||||
|
'srr' => 'Serer',
|
||||||
|
'ksb' => 'Shambala',
|
||||||
|
'shn' => 'Shan',
|
||||||
|
'sn' => 'Shona',
|
||||||
|
'ii' => 'Sichuan Yi',
|
||||||
|
'scn' => 'Sicilian',
|
||||||
|
'sid' => 'Sidamo',
|
||||||
|
'sgn' => 'Sign Language',
|
||||||
|
'bla' => 'Siksika',
|
||||||
|
'zh_Hans' => 'Simplified Chinese',
|
||||||
|
'sd' => 'Sindhi',
|
||||||
|
'si' => 'Sinhala',
|
||||||
|
'sit' => 'Sino-Tibetan Language',
|
||||||
|
'sio' => 'Siouan Language',
|
||||||
|
'sms' => 'Skolt Sami',
|
||||||
|
'den' => 'Slave',
|
||||||
|
'sla' => 'Slavic Language',
|
||||||
|
'sk' => 'Slovak',
|
||||||
|
'sl' => 'Slovenian',
|
||||||
|
'xog' => 'Soga',
|
||||||
|
'sog' => 'Sogdien',
|
||||||
|
'so' => 'Somali',
|
||||||
|
'son' => 'Songhai',
|
||||||
|
'snk' => 'Soninke',
|
||||||
|
'wen' => 'Sorbian Language',
|
||||||
|
'sai' => 'South American Indian Language',
|
||||||
|
'nr' => 'South Ndebele',
|
||||||
|
'alt' => 'Southern Altai',
|
||||||
|
'sma' => 'Southern Sami',
|
||||||
|
'st' => 'Southern Sotho',
|
||||||
|
'es' => 'Spanish',
|
||||||
|
'srn' => 'Sranan Tongo',
|
||||||
|
'suk' => 'Sukuma',
|
||||||
|
'sux' => 'Sumerian',
|
||||||
|
'su' => 'Sundanese',
|
||||||
|
'sus' => 'Susu',
|
||||||
|
'sw' => 'Swahili',
|
||||||
|
'ss' => 'Swati',
|
||||||
|
'sv' => 'Swedish',
|
||||||
|
'fr_CH' => 'Swiss French',
|
||||||
|
'gsw' => 'Swiss German',
|
||||||
|
'de_CH' => 'Swiss High German',
|
||||||
|
'syr' => 'Syriac',
|
||||||
|
'shi' => 'Tachelhit',
|
||||||
|
'tl' => 'Tagalog',
|
||||||
|
'ty' => 'Tahitian',
|
||||||
|
'tai' => 'Tai Language',
|
||||||
|
'dav' => 'Taita',
|
||||||
|
'tg' => 'Tajik',
|
||||||
|
'tmh' => 'Tamashek',
|
||||||
|
'ta' => 'Tamil',
|
||||||
|
'trv' => 'Taroko',
|
||||||
|
'twq' => 'Tasawaq',
|
||||||
|
'tt' => 'Tatar',
|
||||||
|
'te' => 'Telugu',
|
||||||
|
'ter' => 'Tereno',
|
||||||
|
'teo' => 'Teso',
|
||||||
|
'tet' => 'Tetum',
|
||||||
|
'th' => 'Thai',
|
||||||
|
'bo' => 'Tibetan',
|
||||||
|
'tig' => 'Tigre',
|
||||||
|
'ti' => 'Tigrinya',
|
||||||
|
'tem' => 'Timne',
|
||||||
|
'tiv' => 'Tiv',
|
||||||
|
'tli' => 'Tlingit',
|
||||||
|
'tpi' => 'Tok Pisin',
|
||||||
|
'tkl' => 'Tokelau',
|
||||||
|
'to' => 'Tongan',
|
||||||
|
'zh_Hant' => 'Traditional Chinese',
|
||||||
|
'tsi' => 'Tsimshian',
|
||||||
|
'ts' => 'Tsonga',
|
||||||
|
'tn' => 'Tswana',
|
||||||
|
'tum' => 'Tumbuka',
|
||||||
|
'tup' => 'Tupi Language',
|
||||||
|
'tr' => 'Turkish',
|
||||||
|
'tk' => 'Turkmen',
|
||||||
|
'tvl' => 'Tuvalu',
|
||||||
|
'tyv' => 'Tuvinian',
|
||||||
|
'tw' => 'Twi',
|
||||||
|
'kcg' => 'Tyap',
|
||||||
|
'en_US' => 'U.S. English',
|
||||||
|
'udm' => 'Udmurt',
|
||||||
|
'uga' => 'Ugaritic',
|
||||||
|
'ug' => 'Uighur',
|
||||||
|
'uk' => 'Ukrainian',
|
||||||
|
'umb' => 'Umbundu',
|
||||||
|
'und' => 'Unknown Language',
|
||||||
|
'hsb' => 'Upper Sorbian',
|
||||||
|
'ur' => 'Urdu',
|
||||||
|
'uz' => 'Uzbek',
|
||||||
|
'vai' => 'Vai',
|
||||||
|
've' => 'Venda',
|
||||||
|
'vi' => 'Vietnamese',
|
||||||
|
'vo' => 'Volapük',
|
||||||
|
'vot' => 'Votic',
|
||||||
|
'vun' => 'Vunjo',
|
||||||
|
'wak' => 'Wakashan Language',
|
||||||
|
'wal' => 'Walamo',
|
||||||
|
'wa' => 'Walloon',
|
||||||
|
'wae' => 'Walser',
|
||||||
|
'war' => 'Waray',
|
||||||
|
'was' => 'Washo',
|
||||||
|
'cy' => 'Welsh',
|
||||||
|
'fy' => 'Western Frisian',
|
||||||
|
'wo' => 'Wolof',
|
||||||
|
'xh' => 'Xhosa',
|
||||||
|
'yav' => 'Yangben',
|
||||||
|
'yao' => 'Yao',
|
||||||
|
'yap' => 'Yapese',
|
||||||
|
'yi' => 'Yiddish',
|
||||||
|
'yo' => 'Yoruba',
|
||||||
|
'ypk' => 'Yupik Language',
|
||||||
|
'znd' => 'Zande',
|
||||||
|
'zap' => 'Zapotec',
|
||||||
|
'dje' => 'Zarma',
|
||||||
|
'zza' => 'Zaza',
|
||||||
|
'zen' => 'Zenaga',
|
||||||
|
'za' => 'Zhuang',
|
||||||
|
'zu' => 'Zulu',
|
||||||
|
'zun' => 'Zuni',
|
||||||
|
),
|
||||||
|
'Scripts' => array(
|
||||||
|
'Arab' => 'Arabic',
|
||||||
|
'Armn' => 'Armenian',
|
||||||
|
'Avst' => 'Avestan',
|
||||||
|
'Bali' => 'Balinese',
|
||||||
|
'Bamu' => 'Bamum',
|
||||||
|
'Batk' => 'Batak',
|
||||||
|
'Beng' => 'Bengali',
|
||||||
|
'Blis' => 'Blissymbols',
|
||||||
|
'Phlv' => 'Book Pahlavi',
|
||||||
|
'Bopo' => 'Bopomofo',
|
||||||
|
'Brah' => 'Brahmi',
|
||||||
|
'Brai' => 'Braille',
|
||||||
|
'Bugi' => 'Buginese',
|
||||||
|
'Buhd' => 'Buhid',
|
||||||
|
'Cari' => 'Carian',
|
||||||
|
'Cakm' => 'Chakma',
|
||||||
|
'Cham' => 'Cham',
|
||||||
|
'Cher' => 'Cherokee',
|
||||||
|
'Cirt' => 'Cirth',
|
||||||
|
'Zyyy' => 'Common',
|
||||||
|
'Copt' => 'Coptic',
|
||||||
|
'Cprt' => 'Cypriot',
|
||||||
|
'Cyrl' => 'Cyrillic',
|
||||||
|
'Dsrt' => 'Deseret',
|
||||||
|
'Deva' => 'Devanagari',
|
||||||
|
'Syrn' => 'Eastern Syriac',
|
||||||
|
'Egyd' => 'Egyptian demotic',
|
||||||
|
'Egyh' => 'Egyptian hieratic',
|
||||||
|
'Egyp' => 'Egyptian hieroglyphs',
|
||||||
|
'Syre' => 'Estrangelo Syriac',
|
||||||
|
'Ethi' => 'Ethiopic',
|
||||||
|
'Latf' => 'Fraktur Latin',
|
||||||
|
'Lisu' => 'Fraser',
|
||||||
|
'Latg' => 'Gaelic Latin',
|
||||||
|
'Geor' => 'Georgian',
|
||||||
|
'Geok' => 'Georgian Khutsuri',
|
||||||
|
'Glag' => 'Glagolitic',
|
||||||
|
'Goth' => 'Gothic',
|
||||||
|
'Gran' => 'Grantha',
|
||||||
|
'Grek' => 'Greek',
|
||||||
|
'Gujr' => 'Gujarati',
|
||||||
|
'Guru' => 'Gurmukhi',
|
||||||
|
'Hani' => 'Han',
|
||||||
|
'Hang' => 'Hangul',
|
||||||
|
'Hano' => 'Hanunoo',
|
||||||
|
'Hebr' => 'Hebrew',
|
||||||
|
'Hira' => 'Hiragana',
|
||||||
|
'Armi' => 'Imperial Aramaic',
|
||||||
|
'Inds' => 'Indus',
|
||||||
|
'Zinh' => 'Inherited',
|
||||||
|
'Phli' => 'Inscriptional Pahlavi',
|
||||||
|
'Prti' => 'Inscriptional Parthian',
|
||||||
|
'Jpan' => 'Japanese',
|
||||||
|
'Java' => 'Javanese',
|
||||||
|
'Kthi' => 'Kaithi',
|
||||||
|
'Knda' => 'Kannada',
|
||||||
|
'Kana' => 'Katakana',
|
||||||
|
'Hrkt' => 'Katakana or Hiragana',
|
||||||
|
'Kali' => 'Kayah Li',
|
||||||
|
'Khar' => 'Kharoshthi',
|
||||||
|
'Khmr' => 'Khmer',
|
||||||
|
'Kore' => 'Korean',
|
||||||
|
'Lana' => 'Lanna',
|
||||||
|
'Laoo' => 'Lao',
|
||||||
|
'Latn' => 'Latin',
|
||||||
|
'Lepc' => 'Lepcha',
|
||||||
|
'Limb' => 'Limbu',
|
||||||
|
'Lina' => 'Linear A',
|
||||||
|
'Linb' => 'Linear B',
|
||||||
|
'Lyci' => 'Lycian',
|
||||||
|
'Lydi' => 'Lydian',
|
||||||
|
'Mlym' => 'Malayalam',
|
||||||
|
'Mand' => 'Mandaean',
|
||||||
|
'Mani' => 'Manichaean',
|
||||||
|
'Zmth' => 'Mathematical Notation',
|
||||||
|
'Maya' => 'Mayan hieroglyphs',
|
||||||
|
'Mtei' => 'Meitei Mayek',
|
||||||
|
'Mero' => 'Meroitic',
|
||||||
|
'Merc' => 'Meroitic Cursive',
|
||||||
|
'Mong' => 'Mongolian',
|
||||||
|
'Moon' => 'Moon',
|
||||||
|
'Mymr' => 'Myanmar',
|
||||||
|
'Nkoo' => 'N’Ko',
|
||||||
|
'Nkgb' => 'Naxi Geba',
|
||||||
|
'Talu' => 'New Tai Lue',
|
||||||
|
'Ogam' => 'Ogham',
|
||||||
|
'Olck' => 'Ol Chiki',
|
||||||
|
'Cyrs' => 'Old Church Slavonic Cyrillic',
|
||||||
|
'Hung' => 'Old Hungarian',
|
||||||
|
'Ital' => 'Old Italic',
|
||||||
|
'Perm' => 'Old Permic',
|
||||||
|
'Xpeo' => 'Old Persian',
|
||||||
|
'Sarb' => 'Old South Arabian',
|
||||||
|
'Orya' => 'Oriya',
|
||||||
|
'Orkh' => 'Orkhon',
|
||||||
|
'Osma' => 'Osmanya',
|
||||||
|
'Hmng' => 'Pahawh Hmong',
|
||||||
|
'Phag' => 'Phags-pa',
|
||||||
|
'Phnx' => 'Phoenician',
|
||||||
|
'Plrd' => 'Pollard Phonetic',
|
||||||
|
'Phlp' => 'Psalter Pahlavi',
|
||||||
|
'Rjng' => 'Rejang',
|
||||||
|
'Roro' => 'Rongorongo',
|
||||||
|
'Runr' => 'Runic',
|
||||||
|
'Samr' => 'Samaritan',
|
||||||
|
'Sara' => 'Sarati',
|
||||||
|
'Saur' => 'Saurashtra',
|
||||||
|
'Shaw' => 'Shavian',
|
||||||
|
'Sgnw' => 'SignWriting',
|
||||||
|
'Hans' => 'Simplified',
|
||||||
|
'Sinh' => 'Sinhala',
|
||||||
|
'Xsux' => 'Sumero-Akkadian Cuneiform',
|
||||||
|
'Sund' => 'Sundanese',
|
||||||
|
'Sylo' => 'Syloti Nagri',
|
||||||
|
'Zsym' => 'Symbols',
|
||||||
|
'Syrc' => 'Syriac',
|
||||||
|
'Tglg' => 'Tagalog',
|
||||||
|
'Tagb' => 'Tagbanwa',
|
||||||
|
'Tale' => 'Tai Le',
|
||||||
|
'Tavt' => 'Tai Viet',
|
||||||
|
'Taml' => 'Tamil',
|
||||||
|
'Telu' => 'Telugu',
|
||||||
|
'Teng' => 'Tengwar',
|
||||||
|
'Thaa' => 'Thaana',
|
||||||
|
'Thai' => 'Thai',
|
||||||
|
'Tibt' => 'Tibetan',
|
||||||
|
'Tfng' => 'Tifinagh',
|
||||||
|
'Hant' => 'Traditional',
|
||||||
|
'Ugar' => 'Ugaritic',
|
||||||
|
'Cans' => 'Unified Canadian Aboriginal Syllabics',
|
||||||
|
'Zzzz' => 'Unknown Script',
|
||||||
|
'Zxxx' => 'Unwritten',
|
||||||
|
'Vaii' => 'Vai',
|
||||||
|
'Wara' => 'Varang Kshiti',
|
||||||
|
'Visp' => 'Visible Speech',
|
||||||
|
'Syrj' => 'Western Syriac',
|
||||||
|
'Yiii' => 'Yi',
|
||||||
|
),
|
||||||
|
);
|
279
src/Symfony/Component/Intl/Resources/data/locales/en.php
Normal file
279
src/Symfony/Component/Intl/Resources/data/locales/en.php
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Locales' => array(
|
||||||
|
'af' => 'Afrikaans',
|
||||||
|
'af_NA' => 'Afrikaans (Namibia)',
|
||||||
|
'agq' => 'Aghem',
|
||||||
|
'ak' => 'Akan',
|
||||||
|
'sq' => 'Albanian',
|
||||||
|
'am' => 'Amharic',
|
||||||
|
'ar' => 'Arabic',
|
||||||
|
'ar_DZ' => 'Arabic (Algeria)',
|
||||||
|
'ar_JO' => 'Arabic (Jordan)',
|
||||||
|
'ar_LB' => 'Arabic (Lebanon)',
|
||||||
|
'ar_MA' => 'Arabic (Morocco)',
|
||||||
|
'ar_QA' => 'Arabic (Qatar)',
|
||||||
|
'ar_SA' => 'Arabic (Saudi Arabia)',
|
||||||
|
'ar_SY' => 'Arabic (Syria)',
|
||||||
|
'ar_TN' => 'Arabic (Tunisia)',
|
||||||
|
'ar_YE' => 'Arabic (Yemen)',
|
||||||
|
'hy' => 'Armenian',
|
||||||
|
'as' => 'Assamese',
|
||||||
|
'asa' => 'Asu',
|
||||||
|
'az' => 'Azerbaijani',
|
||||||
|
'az_Cyrl' => 'Azerbaijani (Cyrillic)',
|
||||||
|
'az_Latn' => 'Azerbaijani (Latin)',
|
||||||
|
'ksf' => 'Bafia',
|
||||||
|
'bm' => 'Bambara',
|
||||||
|
'bas' => 'Basaa',
|
||||||
|
'eu' => 'Basque',
|
||||||
|
'be' => 'Belarusian',
|
||||||
|
'bem' => 'Bemba',
|
||||||
|
'bez' => 'Bena',
|
||||||
|
'bn' => 'Bengali',
|
||||||
|
'bn_IN' => 'Bengali (India)',
|
||||||
|
'brx' => 'Bodo',
|
||||||
|
'bs' => 'Bosnian',
|
||||||
|
'br' => 'Breton',
|
||||||
|
'bg' => 'Bulgarian',
|
||||||
|
'my' => 'Burmese',
|
||||||
|
'my_MM' => 'Burmese (Myanmar [Burma])',
|
||||||
|
'ca' => 'Catalan',
|
||||||
|
'tzm' => 'Central Morocco Tamazight',
|
||||||
|
'tzm_Latn' => 'Central Morocco Tamazight (Latin)',
|
||||||
|
'chr' => 'Cherokee',
|
||||||
|
'chr_US' => 'Cherokee (United States)',
|
||||||
|
'cgg' => 'Chiga',
|
||||||
|
'zh' => 'Chinese',
|
||||||
|
'zh_Hans_HK' => 'Chinese (Simplified, Hong Kong SAR China)',
|
||||||
|
'zh_Hans_MO' => 'Chinese (Simplified, Macau SAR China)',
|
||||||
|
'zh_Hans_SG' => 'Chinese (Simplified, Singapore)',
|
||||||
|
'zh_Hans' => 'Chinese (Simplified)',
|
||||||
|
'zh_Hant_HK' => 'Chinese (Traditional, Hong Kong SAR China)',
|
||||||
|
'zh_Hant_MO' => 'Chinese (Traditional, Macau SAR China)',
|
||||||
|
'zh_Hant' => 'Chinese (Traditional)',
|
||||||
|
'swc' => 'Congo Swahili',
|
||||||
|
'kw' => 'Cornish',
|
||||||
|
'hr' => 'Croatian',
|
||||||
|
'cs' => 'Czech',
|
||||||
|
'da' => 'Danish',
|
||||||
|
'dua' => 'Duala',
|
||||||
|
'nl' => 'Dutch',
|
||||||
|
'nl_BE' => 'Dutch (Belgium)',
|
||||||
|
'ebu' => 'Embu',
|
||||||
|
'en' => 'English',
|
||||||
|
'en_AU' => 'English (Australia)',
|
||||||
|
'en_BE' => 'English (Belgium)',
|
||||||
|
'en_BZ' => 'English (Belize)',
|
||||||
|
'en_BW' => 'English (Botswana)',
|
||||||
|
'en_CA' => 'English (Canada)',
|
||||||
|
'en_HK' => 'English (Hong Kong SAR China)',
|
||||||
|
'en_IN' => 'English (India)',
|
||||||
|
'en_IE' => 'English (Ireland)',
|
||||||
|
'en_JM' => 'English (Jamaica)',
|
||||||
|
'en_MT' => 'English (Malta)',
|
||||||
|
'en_NA' => 'English (Namibia)',
|
||||||
|
'en_NZ' => 'English (New Zealand)',
|
||||||
|
'en_PK' => 'English (Pakistan)',
|
||||||
|
'en_PH' => 'English (Philippines)',
|
||||||
|
'en_SG' => 'English (Singapore)',
|
||||||
|
'en_ZA' => 'English (South Africa)',
|
||||||
|
'en_TT' => 'English (Trinidad and Tobago)',
|
||||||
|
'en_GB' => 'English (United Kingdom)',
|
||||||
|
'en_US' => 'English (United States)',
|
||||||
|
'en_ZW' => 'English (Zimbabwe)',
|
||||||
|
'eo' => 'Esperanto',
|
||||||
|
'et' => 'Estonian',
|
||||||
|
'ee' => 'Ewe',
|
||||||
|
'ewo' => 'Ewondo',
|
||||||
|
'fo' => 'Faroese',
|
||||||
|
'fil' => 'Filipino',
|
||||||
|
'fil_PH' => 'Filipino (Philippines)',
|
||||||
|
'fi' => 'Finnish',
|
||||||
|
'fr' => 'French',
|
||||||
|
'fr_BE' => 'French (Belgium)',
|
||||||
|
'fr_CA' => 'French (Canada)',
|
||||||
|
'fr_LU' => 'French (Luxembourg)',
|
||||||
|
'fr_CH' => 'French (Switzerland)',
|
||||||
|
'ff' => 'Fulah',
|
||||||
|
'gl' => 'Galician',
|
||||||
|
'lg' => 'Ganda',
|
||||||
|
'ka' => 'Georgian',
|
||||||
|
'de' => 'German',
|
||||||
|
'de_AT' => 'German (Austria)',
|
||||||
|
'de_LI' => 'German (Liechtenstein)',
|
||||||
|
'de_CH' => 'German (Switzerland)',
|
||||||
|
'el' => 'Greek',
|
||||||
|
'el_CY' => 'Greek (Cyprus)',
|
||||||
|
'gu' => 'Gujarati',
|
||||||
|
'guz' => 'Gusii',
|
||||||
|
'ha' => 'Hausa',
|
||||||
|
'ha_Latn' => 'Hausa (Latin)',
|
||||||
|
'haw' => 'Hawaiian',
|
||||||
|
'haw_US' => 'Hawaiian (United States)',
|
||||||
|
'he' => 'Hebrew',
|
||||||
|
'hi' => 'Hindi',
|
||||||
|
'hu' => 'Hungarian',
|
||||||
|
'is' => 'Icelandic',
|
||||||
|
'ig' => 'Igbo',
|
||||||
|
'id' => 'Indonesian',
|
||||||
|
'ga' => 'Irish',
|
||||||
|
'it' => 'Italian',
|
||||||
|
'it_CH' => 'Italian (Switzerland)',
|
||||||
|
'ja' => 'Japanese',
|
||||||
|
'dyo' => 'Jola-Fonyi',
|
||||||
|
'kea' => 'Kabuverdianu',
|
||||||
|
'kab' => 'Kabyle',
|
||||||
|
'kl' => 'Kalaallisut',
|
||||||
|
'kln' => 'Kalenjin',
|
||||||
|
'kam' => 'Kamba',
|
||||||
|
'kn' => 'Kannada',
|
||||||
|
'kk' => 'Kazakh',
|
||||||
|
'kk_Cyrl' => 'Kazakh (Cyrillic)',
|
||||||
|
'km' => 'Khmer',
|
||||||
|
'ki' => 'Kikuyu',
|
||||||
|
'rw' => 'Kinyarwanda',
|
||||||
|
'kok' => 'Konkani',
|
||||||
|
'ko' => 'Korean',
|
||||||
|
'khq' => 'Koyra Chiini',
|
||||||
|
'ses' => 'Koyraboro Senni',
|
||||||
|
'nmg' => 'Kwasio',
|
||||||
|
'lag' => 'Langi',
|
||||||
|
'lv' => 'Latvian',
|
||||||
|
'ln' => 'Lingala',
|
||||||
|
'lt' => 'Lithuanian',
|
||||||
|
'lu' => 'Luba-Katanga',
|
||||||
|
'luo' => 'Luo',
|
||||||
|
'luy' => 'Luyia',
|
||||||
|
'mk' => 'Macedonian',
|
||||||
|
'jmc' => 'Machame',
|
||||||
|
'mgh' => 'Makhuwa-Meetto',
|
||||||
|
'kde' => 'Makonde',
|
||||||
|
'mg' => 'Malagasy',
|
||||||
|
'ms' => 'Malay',
|
||||||
|
'ms_BN' => 'Malay (Brunei)',
|
||||||
|
'ml' => 'Malayalam',
|
||||||
|
'mt' => 'Maltese',
|
||||||
|
'gv' => 'Manx',
|
||||||
|
'mr' => 'Marathi',
|
||||||
|
'mas' => 'Masai',
|
||||||
|
'mer' => 'Meru',
|
||||||
|
'mfe' => 'Morisyen',
|
||||||
|
'mua' => 'Mundang',
|
||||||
|
'naq' => 'Nama',
|
||||||
|
'ne' => 'Nepali',
|
||||||
|
'ne_IN' => 'Nepali (India)',
|
||||||
|
'nd' => 'North Ndebele',
|
||||||
|
'nb' => 'Norwegian Bokmål',
|
||||||
|
'nn' => 'Norwegian Nynorsk',
|
||||||
|
'nus' => 'Nuer',
|
||||||
|
'nyn' => 'Nyankole',
|
||||||
|
'or' => 'Oriya',
|
||||||
|
'om' => 'Oromo',
|
||||||
|
'ps' => 'Pashto',
|
||||||
|
'fa' => 'Persian',
|
||||||
|
'fa_AF' => 'Persian (Afghanistan)',
|
||||||
|
'pl' => 'Polish',
|
||||||
|
'pt' => 'Portuguese',
|
||||||
|
'pt_AO' => 'Portuguese (Angola)',
|
||||||
|
'pt_GW' => 'Portuguese (Guinea-Bissau)',
|
||||||
|
'pt_MZ' => 'Portuguese (Mozambique)',
|
||||||
|
'pt_PT' => 'Portuguese (Portugal)',
|
||||||
|
'pt_ST' => 'Portuguese (São Tomé and Príncipe)',
|
||||||
|
'pa' => 'Punjabi',
|
||||||
|
'pa_Arab' => 'Punjabi (Arabic)',
|
||||||
|
'pa_Guru' => 'Punjabi (Gurmukhi)',
|
||||||
|
'ro' => 'Romanian',
|
||||||
|
'rm' => 'Romansh',
|
||||||
|
'rof' => 'Rombo',
|
||||||
|
'rn' => 'Rundi',
|
||||||
|
'ru' => 'Russian',
|
||||||
|
'ru_UA' => 'Russian (Ukraine)',
|
||||||
|
'rwk' => 'Rwa',
|
||||||
|
'saq' => 'Samburu',
|
||||||
|
'sg' => 'Sango',
|
||||||
|
'sbp' => 'Sangu',
|
||||||
|
'seh' => 'Sena',
|
||||||
|
'sr' => 'Serbian',
|
||||||
|
'sr_Cyrl_BA' => 'Serbian (Cyrillic, Bosnia and Herzegovina)',
|
||||||
|
'sr_Cyrl' => 'Serbian (Cyrillic)',
|
||||||
|
'sr_Latn_ME' => 'Serbian (Latin, Montenegro)',
|
||||||
|
'sr_Latn' => 'Serbian (Latin)',
|
||||||
|
'ksb' => 'Shambala',
|
||||||
|
'sn' => 'Shona',
|
||||||
|
'ii' => 'Sichuan Yi',
|
||||||
|
'si' => 'Sinhala',
|
||||||
|
'sk' => 'Slovak',
|
||||||
|
'sl' => 'Slovenian',
|
||||||
|
'xog' => 'Soga',
|
||||||
|
'so' => 'Somali',
|
||||||
|
'es' => 'Spanish',
|
||||||
|
'es_AR' => 'Spanish (Argentina)',
|
||||||
|
'es_BO' => 'Spanish (Bolivia)',
|
||||||
|
'es_CL' => 'Spanish (Chile)',
|
||||||
|
'es_CO' => 'Spanish (Colombia)',
|
||||||
|
'es_CR' => 'Spanish (Costa Rica)',
|
||||||
|
'es_DO' => 'Spanish (Dominican Republic)',
|
||||||
|
'es_EC' => 'Spanish (Ecuador)',
|
||||||
|
'es_SV' => 'Spanish (El Salvador)',
|
||||||
|
'es_GQ' => 'Spanish (Equatorial Guinea)',
|
||||||
|
'es_GT' => 'Spanish (Guatemala)',
|
||||||
|
'es_HN' => 'Spanish (Honduras)',
|
||||||
|
'es_MX' => 'Spanish (Mexico)',
|
||||||
|
'es_NI' => 'Spanish (Nicaragua)',
|
||||||
|
'es_PA' => 'Spanish (Panama)',
|
||||||
|
'es_PY' => 'Spanish (Paraguay)',
|
||||||
|
'es_PE' => 'Spanish (Peru)',
|
||||||
|
'es_PR' => 'Spanish (Puerto Rico)',
|
||||||
|
'es_US' => 'Spanish (United States)',
|
||||||
|
'es_UY' => 'Spanish (Uruguay)',
|
||||||
|
'es_VE' => 'Spanish (Venezuela)',
|
||||||
|
'sw' => 'Swahili',
|
||||||
|
'sw_KE' => 'Swahili (Kenya)',
|
||||||
|
'sv' => 'Swedish',
|
||||||
|
'sv_FI' => 'Swedish (Finland)',
|
||||||
|
'gsw' => 'Swiss German',
|
||||||
|
'shi' => 'Tachelhit',
|
||||||
|
'shi_Tfng' => 'Tachelhit (Tifinagh)',
|
||||||
|
'dav' => 'Taita',
|
||||||
|
'ta' => 'Tamil',
|
||||||
|
'twq' => 'Tasawaq',
|
||||||
|
'te' => 'Telugu',
|
||||||
|
'teo' => 'Teso',
|
||||||
|
'th' => 'Thai',
|
||||||
|
'bo' => 'Tibetan',
|
||||||
|
'ti' => 'Tigrinya',
|
||||||
|
'ti_ER' => 'Tigrinya (Eritrea)',
|
||||||
|
'to' => 'Tongan',
|
||||||
|
'tr' => 'Turkish',
|
||||||
|
'uk' => 'Ukrainian',
|
||||||
|
'ur' => 'Urdu',
|
||||||
|
'ur_IN' => 'Urdu (India)',
|
||||||
|
'uz' => 'Uzbek',
|
||||||
|
'uz_Arab' => 'Uzbek (Arabic)',
|
||||||
|
'uz_Cyrl' => 'Uzbek (Cyrillic)',
|
||||||
|
'uz_Latn' => 'Uzbek (Latin)',
|
||||||
|
'vai' => 'Vai',
|
||||||
|
'vai_Latn_LR' => 'Vai (Latin, Liberia)',
|
||||||
|
'vai_Latn' => 'Vai (Latin)',
|
||||||
|
'vai_Vaii_LR' => 'Vai (Vai, Liberia)',
|
||||||
|
'vai_Vaii' => 'Vai (Vai)',
|
||||||
|
'vi' => 'Vietnamese',
|
||||||
|
'vun' => 'Vunjo',
|
||||||
|
'cy' => 'Welsh',
|
||||||
|
'yav' => 'Yangben',
|
||||||
|
'yo' => 'Yoruba',
|
||||||
|
'dje' => 'Zarma',
|
||||||
|
'zu' => 'Zulu',
|
||||||
|
),
|
||||||
|
);
|
272
src/Symfony/Component/Intl/Resources/data/region/en.php
Normal file
272
src/Symfony/Component/Intl/Resources/data/region/en.php
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Countries' => array(
|
||||||
|
'AF' => 'Afghanistan',
|
||||||
|
'AX' => 'Åland Islands',
|
||||||
|
'AL' => 'Albania',
|
||||||
|
'DZ' => 'Algeria',
|
||||||
|
'AS' => 'American Samoa',
|
||||||
|
'AD' => 'Andorra',
|
||||||
|
'AO' => 'Angola',
|
||||||
|
'AI' => 'Anguilla',
|
||||||
|
'AQ' => 'Antarctica',
|
||||||
|
'AG' => 'Antigua and Barbuda',
|
||||||
|
'AR' => 'Argentina',
|
||||||
|
'AM' => 'Armenia',
|
||||||
|
'AW' => 'Aruba',
|
||||||
|
'AC' => 'Ascension Island',
|
||||||
|
'AU' => 'Australia',
|
||||||
|
'AT' => 'Austria',
|
||||||
|
'AZ' => 'Azerbaijan',
|
||||||
|
'BS' => 'Bahamas',
|
||||||
|
'BH' => 'Bahrain',
|
||||||
|
'BD' => 'Bangladesh',
|
||||||
|
'BB' => 'Barbados',
|
||||||
|
'BY' => 'Belarus',
|
||||||
|
'BE' => 'Belgium',
|
||||||
|
'BZ' => 'Belize',
|
||||||
|
'BJ' => 'Benin',
|
||||||
|
'BM' => 'Bermuda',
|
||||||
|
'BT' => 'Bhutan',
|
||||||
|
'BO' => 'Bolivia',
|
||||||
|
'BA' => 'Bosnia and Herzegovina',
|
||||||
|
'BW' => 'Botswana',
|
||||||
|
'BV' => 'Bouvet Island',
|
||||||
|
'BR' => 'Brazil',
|
||||||
|
'IO' => 'British Indian Ocean Territory',
|
||||||
|
'VG' => 'British Virgin Islands',
|
||||||
|
'BN' => 'Brunei',
|
||||||
|
'BG' => 'Bulgaria',
|
||||||
|
'BF' => 'Burkina Faso',
|
||||||
|
'BI' => 'Burundi',
|
||||||
|
'KH' => 'Cambodia',
|
||||||
|
'CM' => 'Cameroon',
|
||||||
|
'CA' => 'Canada',
|
||||||
|
'IC' => 'Canary Islands',
|
||||||
|
'CV' => 'Cape Verde',
|
||||||
|
'KY' => 'Cayman Islands',
|
||||||
|
'CF' => 'Central African Republic',
|
||||||
|
'EA' => 'Ceuta and Melilla',
|
||||||
|
'TD' => 'Chad',
|
||||||
|
'CL' => 'Chile',
|
||||||
|
'CN' => 'China',
|
||||||
|
'CX' => 'Christmas Island',
|
||||||
|
'CP' => 'Clipperton Island',
|
||||||
|
'CC' => 'Cocos [Keeling] Islands',
|
||||||
|
'CO' => 'Colombia',
|
||||||
|
'KM' => 'Comoros',
|
||||||
|
'CG' => 'Congo - Brazzaville',
|
||||||
|
'CD' => 'Congo - Kinshasa',
|
||||||
|
'CK' => 'Cook Islands',
|
||||||
|
'CR' => 'Costa Rica',
|
||||||
|
'CI' => 'Côte d’Ivoire',
|
||||||
|
'HR' => 'Croatia',
|
||||||
|
'CU' => 'Cuba',
|
||||||
|
'CW' => 'Curaçao',
|
||||||
|
'CY' => 'Cyprus',
|
||||||
|
'CZ' => 'Czech Republic',
|
||||||
|
'DK' => 'Denmark',
|
||||||
|
'DG' => 'Diego Garcia',
|
||||||
|
'DJ' => 'Djibouti',
|
||||||
|
'DM' => 'Dominica',
|
||||||
|
'DO' => 'Dominican Republic',
|
||||||
|
'EC' => 'Ecuador',
|
||||||
|
'EG' => 'Egypt',
|
||||||
|
'SV' => 'El Salvador',
|
||||||
|
'GQ' => 'Equatorial Guinea',
|
||||||
|
'ER' => 'Eritrea',
|
||||||
|
'EE' => 'Estonia',
|
||||||
|
'ET' => 'Ethiopia',
|
||||||
|
'EU' => 'European Union',
|
||||||
|
'FK' => 'Falkland Islands',
|
||||||
|
'FO' => 'Faroe Islands',
|
||||||
|
'FJ' => 'Fiji',
|
||||||
|
'FI' => 'Finland',
|
||||||
|
'FR' => 'France',
|
||||||
|
'GF' => 'French Guiana',
|
||||||
|
'PF' => 'French Polynesia',
|
||||||
|
'TF' => 'French Southern Territories',
|
||||||
|
'GA' => 'Gabon',
|
||||||
|
'GM' => 'Gambia',
|
||||||
|
'GE' => 'Georgia',
|
||||||
|
'DE' => 'Germany',
|
||||||
|
'GH' => 'Ghana',
|
||||||
|
'GI' => 'Gibraltar',
|
||||||
|
'GR' => 'Greece',
|
||||||
|
'GL' => 'Greenland',
|
||||||
|
'GD' => 'Grenada',
|
||||||
|
'GP' => 'Guadeloupe',
|
||||||
|
'GU' => 'Guam',
|
||||||
|
'GT' => 'Guatemala',
|
||||||
|
'GG' => 'Guernsey',
|
||||||
|
'GN' => 'Guinea',
|
||||||
|
'GW' => 'Guinea-Bissau',
|
||||||
|
'GY' => 'Guyana',
|
||||||
|
'HT' => 'Haiti',
|
||||||
|
'HM' => 'Heard Island and McDonald Islands',
|
||||||
|
'HN' => 'Honduras',
|
||||||
|
'HK' => 'Hong Kong SAR China',
|
||||||
|
'HU' => 'Hungary',
|
||||||
|
'IS' => 'Iceland',
|
||||||
|
'IN' => 'India',
|
||||||
|
'ID' => 'Indonesia',
|
||||||
|
'IR' => 'Iran',
|
||||||
|
'IQ' => 'Iraq',
|
||||||
|
'IE' => 'Ireland',
|
||||||
|
'IM' => 'Isle of Man',
|
||||||
|
'IL' => 'Israel',
|
||||||
|
'IT' => 'Italy',
|
||||||
|
'JM' => 'Jamaica',
|
||||||
|
'JP' => 'Japan',
|
||||||
|
'JE' => 'Jersey',
|
||||||
|
'JO' => 'Jordan',
|
||||||
|
'KZ' => 'Kazakhstan',
|
||||||
|
'KE' => 'Kenya',
|
||||||
|
'KI' => 'Kiribati',
|
||||||
|
'KW' => 'Kuwait',
|
||||||
|
'KG' => 'Kyrgyzstan',
|
||||||
|
'LA' => 'Laos',
|
||||||
|
'LV' => 'Latvia',
|
||||||
|
'LB' => 'Lebanon',
|
||||||
|
'LS' => 'Lesotho',
|
||||||
|
'LR' => 'Liberia',
|
||||||
|
'LY' => 'Libya',
|
||||||
|
'LI' => 'Liechtenstein',
|
||||||
|
'LT' => 'Lithuania',
|
||||||
|
'LU' => 'Luxembourg',
|
||||||
|
'MO' => 'Macau SAR China',
|
||||||
|
'MK' => 'Macedonia',
|
||||||
|
'MG' => 'Madagascar',
|
||||||
|
'MW' => 'Malawi',
|
||||||
|
'MY' => 'Malaysia',
|
||||||
|
'MV' => 'Maldives',
|
||||||
|
'ML' => 'Mali',
|
||||||
|
'MT' => 'Malta',
|
||||||
|
'MH' => 'Marshall Islands',
|
||||||
|
'MQ' => 'Martinique',
|
||||||
|
'MR' => 'Mauritania',
|
||||||
|
'MU' => 'Mauritius',
|
||||||
|
'YT' => 'Mayotte',
|
||||||
|
'MX' => 'Mexico',
|
||||||
|
'FM' => 'Micronesia',
|
||||||
|
'MD' => 'Moldova',
|
||||||
|
'MC' => 'Monaco',
|
||||||
|
'MN' => 'Mongolia',
|
||||||
|
'ME' => 'Montenegro',
|
||||||
|
'MS' => 'Montserrat',
|
||||||
|
'MA' => 'Morocco',
|
||||||
|
'MZ' => 'Mozambique',
|
||||||
|
'MM' => 'Myanmar [Burma]',
|
||||||
|
'NA' => 'Namibia',
|
||||||
|
'NR' => 'Nauru',
|
||||||
|
'NP' => 'Nepal',
|
||||||
|
'NL' => 'Netherlands',
|
||||||
|
'AN' => 'Netherlands Antilles',
|
||||||
|
'NC' => 'New Caledonia',
|
||||||
|
'NZ' => 'New Zealand',
|
||||||
|
'NI' => 'Nicaragua',
|
||||||
|
'NE' => 'Niger',
|
||||||
|
'NG' => 'Nigeria',
|
||||||
|
'NU' => 'Niue',
|
||||||
|
'NF' => 'Norfolk Island',
|
||||||
|
'KP' => 'North Korea',
|
||||||
|
'MP' => 'Northern Mariana Islands',
|
||||||
|
'NO' => 'Norway',
|
||||||
|
'OM' => 'Oman',
|
||||||
|
'QO' => 'Outlying Oceania',
|
||||||
|
'PK' => 'Pakistan',
|
||||||
|
'PW' => 'Palau',
|
||||||
|
'PS' => 'Palestinian Territories',
|
||||||
|
'PA' => 'Panama',
|
||||||
|
'PG' => 'Papua New Guinea',
|
||||||
|
'PY' => 'Paraguay',
|
||||||
|
'PE' => 'Peru',
|
||||||
|
'PH' => 'Philippines',
|
||||||
|
'PN' => 'Pitcairn Islands',
|
||||||
|
'PL' => 'Poland',
|
||||||
|
'PT' => 'Portugal',
|
||||||
|
'PR' => 'Puerto Rico',
|
||||||
|
'QA' => 'Qatar',
|
||||||
|
'RE' => 'Réunion',
|
||||||
|
'RO' => 'Romania',
|
||||||
|
'RU' => 'Russia',
|
||||||
|
'RW' => 'Rwanda',
|
||||||
|
'BL' => 'Saint Barthélemy',
|
||||||
|
'SH' => 'Saint Helena',
|
||||||
|
'KN' => 'Saint Kitts and Nevis',
|
||||||
|
'LC' => 'Saint Lucia',
|
||||||
|
'MF' => 'Saint Martin',
|
||||||
|
'PM' => 'Saint Pierre and Miquelon',
|
||||||
|
'VC' => 'Saint Vincent and the Grenadines',
|
||||||
|
'WS' => 'Samoa',
|
||||||
|
'SM' => 'San Marino',
|
||||||
|
'ST' => 'São Tomé and Príncipe',
|
||||||
|
'SA' => 'Saudi Arabia',
|
||||||
|
'SN' => 'Senegal',
|
||||||
|
'RS' => 'Serbia',
|
||||||
|
'CS' => 'Serbia and Montenegro',
|
||||||
|
'SC' => 'Seychelles',
|
||||||
|
'SL' => 'Sierra Leone',
|
||||||
|
'SG' => 'Singapore',
|
||||||
|
'SX' => 'Sint Maarten',
|
||||||
|
'SK' => 'Slovakia',
|
||||||
|
'SI' => 'Slovenia',
|
||||||
|
'SB' => 'Solomon Islands',
|
||||||
|
'SO' => 'Somalia',
|
||||||
|
'ZA' => 'South Africa',
|
||||||
|
'GS' => 'South Georgia and the South Sandwich Islands',
|
||||||
|
'KR' => 'South Korea',
|
||||||
|
'ES' => 'Spain',
|
||||||
|
'LK' => 'Sri Lanka',
|
||||||
|
'SD' => 'Sudan',
|
||||||
|
'SR' => 'Suriname',
|
||||||
|
'SJ' => 'Svalbard and Jan Mayen',
|
||||||
|
'SZ' => 'Swaziland',
|
||||||
|
'SE' => 'Sweden',
|
||||||
|
'CH' => 'Switzerland',
|
||||||
|
'SY' => 'Syria',
|
||||||
|
'TW' => 'Taiwan',
|
||||||
|
'TJ' => 'Tajikistan',
|
||||||
|
'TZ' => 'Tanzania',
|
||||||
|
'TH' => 'Thailand',
|
||||||
|
'TL' => 'Timor-Leste',
|
||||||
|
'TG' => 'Togo',
|
||||||
|
'TK' => 'Tokelau',
|
||||||
|
'TO' => 'Tonga',
|
||||||
|
'TT' => 'Trinidad and Tobago',
|
||||||
|
'TA' => 'Tristan da Cunha',
|
||||||
|
'TN' => 'Tunisia',
|
||||||
|
'TR' => 'Turkey',
|
||||||
|
'TM' => 'Turkmenistan',
|
||||||
|
'TC' => 'Turks and Caicos Islands',
|
||||||
|
'TV' => 'Tuvalu',
|
||||||
|
'UM' => 'U.S. Minor Outlying Islands',
|
||||||
|
'VI' => 'U.S. Virgin Islands',
|
||||||
|
'UG' => 'Uganda',
|
||||||
|
'UA' => 'Ukraine',
|
||||||
|
'AE' => 'United Arab Emirates',
|
||||||
|
'GB' => 'United Kingdom',
|
||||||
|
'US' => 'United States',
|
||||||
|
'UY' => 'Uruguay',
|
||||||
|
'UZ' => 'Uzbekistan',
|
||||||
|
'VU' => 'Vanuatu',
|
||||||
|
'VA' => 'Vatican City',
|
||||||
|
'VE' => 'Venezuela',
|
||||||
|
'VN' => 'Vietnam',
|
||||||
|
'WF' => 'Wallis and Futuna',
|
||||||
|
'EH' => 'Western Sahara',
|
||||||
|
'YE' => 'Yemen',
|
||||||
|
'ZM' => 'Zambia',
|
||||||
|
'ZW' => 'Zimbabwe',
|
||||||
|
),
|
||||||
|
);
|
1
src/Symfony/Component/Intl/Resources/data/version.txt
Normal file
1
src/Symfony/Component/Intl/Resources/data/version.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
4.8.1.1
|
@ -9,15 +9,15 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Collator\StubCollator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stub implementation for the Collator class of the intl extension
|
* Stub implementation for the Collator class of the intl extension
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
* @see Symfony\Component\Collator\Stub\StubCollator
|
*
|
||||||
|
* @see Symfony\Component\Intl\Collator\StubCollator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Symfony\Component\Locale\Stub\StubCollator;
|
|
||||||
|
|
||||||
class Collator extends StubCollator
|
class Collator extends StubCollator
|
||||||
{
|
{
|
||||||
}
|
}
|
@ -9,15 +9,15 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\DateFormatter\StubIntlDateFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stub implementation for the IntlDateFormatter class of the intl extension
|
* Stub implementation for the IntlDateFormatter class of the intl extension
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
* @see Symfony\Component\IntlDateFormatter\Stub\StubIntlDateFormatter
|
*
|
||||||
|
* @see Symfony\Component\Intl\DateFormatter\StubIntlDateFormatter
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Symfony\Component\Locale\Stub\StubIntlDateFormatter;
|
|
||||||
|
|
||||||
class IntlDateFormatter extends StubIntlDateFormatter
|
class IntlDateFormatter extends StubIntlDateFormatter
|
||||||
{
|
{
|
||||||
}
|
}
|
@ -9,15 +9,15 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Locale\StubLocale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stub implementation for the Locale class of the intl extension
|
* Stub implementation for the Locale class of the intl extension
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
* @see Symfony\Component\Locale\Stub\StubLocale
|
*
|
||||||
|
* @see Symfony\Component\Intl\Locale\StubLocale
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Symfony\Component\Locale\Stub\StubLocale;
|
|
||||||
|
|
||||||
class Locale extends StubLocale
|
class Locale extends StubLocale
|
||||||
{
|
{
|
||||||
}
|
}
|
@ -9,15 +9,15 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\NumberFormatter\StubNumberFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stub implementation for the NumberFormatter class of the intl extension
|
* Stub implementation for the NumberFormatter class of the intl extension
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
* @see Symfony\Component\Locale\Stub\StubNumberFormatter
|
*
|
||||||
|
* @see Symfony\Component\Intl\NumberFormatter\StubNumberFormatter
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Symfony\Component\Locale\Stub\StubNumberFormatter;
|
|
||||||
|
|
||||||
class NumberFormatter extends StubNumberFormatter
|
class NumberFormatter extends StubNumberFormatter
|
||||||
{
|
{
|
||||||
}
|
}
|
80
src/Symfony/Component/Intl/Resources/stubs/functions.php
Normal file
80
src/Symfony/Component/Intl/Resources/stubs/functions.php
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Globals\StubIntlGlobals;
|
||||||
|
|
||||||
|
if (!function_exists('intl_is_failure')) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stub implementation for the {@link intl_is_failure()} function of the intl
|
||||||
|
* extension.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @param integer $errorCode The error code returned by intl_get_error_code().
|
||||||
|
*
|
||||||
|
* @return Boolean Whether the error code indicates an error.
|
||||||
|
*
|
||||||
|
* @see \Symfony\Component\Intl\Globals\StubIntlGlobals::isFailure
|
||||||
|
*/
|
||||||
|
function intl_is_failure($errorCode)
|
||||||
|
{
|
||||||
|
return StubIntlGlobals::isFailure($errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stub implementation for the {@link intl_get_error_code()} function of the
|
||||||
|
* intl extension.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @return Boolean The error code of the last intl function call or
|
||||||
|
* StubIntlGlobals::U_ZERO_ERROR if no error occurred.
|
||||||
|
*
|
||||||
|
* @see \Symfony\Component\Intl\Globals\StubIntlGlobals::getErrorCode
|
||||||
|
*/
|
||||||
|
function intl_get_error_code()
|
||||||
|
{
|
||||||
|
return StubIntlGlobals::getErrorCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stub implementation for the {@link intl_get_error_code()} function of the
|
||||||
|
* intl extension.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @return Boolean The error message of the last intl function call or
|
||||||
|
* "U_ZERO_ERROR" if no error occurred.
|
||||||
|
*
|
||||||
|
* @see \Symfony\Component\Intl\Globals\StubIntlGlobals::getErrorMessage
|
||||||
|
*/
|
||||||
|
function intl_get_error_message()
|
||||||
|
{
|
||||||
|
return StubIntlGlobals::getErrorMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stub implementation for the {@link intl_error_name()} function of the intl
|
||||||
|
* extension.
|
||||||
|
*
|
||||||
|
* @param integer $errorCode The error code.
|
||||||
|
*
|
||||||
|
* @return string The name of the error code constant.
|
||||||
|
*
|
||||||
|
* @see \Symfony\Component\Intl\Globals\StubIntlGlobals::getErrorName
|
||||||
|
*/
|
||||||
|
function intl_error_name($errorCode)
|
||||||
|
{
|
||||||
|
return StubIntlGlobals::getErrorName($errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Tests\Collator;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Collator\StubCollator;
|
||||||
|
use Symfony\Component\Intl\Locale;
|
||||||
|
use Symfony\Component\Intl\Tests\IntlTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test case for Collator implementations.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
abstract class AbstractCollatorTest extends IntlTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider asortProvider
|
||||||
|
*/
|
||||||
|
public function testAsort($array, $sortFlag, $expected)
|
||||||
|
{
|
||||||
|
$collator = $this->getCollator('en');
|
||||||
|
$collator->asort($array, $sortFlag);
|
||||||
|
$this->assertSame($expected, $array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function asortProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
/* array, sortFlag, expected */
|
||||||
|
array(
|
||||||
|
array('a', 'b', 'c'),
|
||||||
|
StubCollator::SORT_REGULAR,
|
||||||
|
array('a', 'b', 'c'),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
array('c', 'b', 'a'),
|
||||||
|
StubCollator::SORT_REGULAR,
|
||||||
|
array(2 => 'a', 1 => 'b', 0 => 'c'),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
array('b', 'c', 'a'),
|
||||||
|
StubCollator::SORT_REGULAR,
|
||||||
|
array(2 => 'a', 0 => 'b', 1 => 'c'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $locale
|
||||||
|
*
|
||||||
|
* @return \Collator
|
||||||
|
*/
|
||||||
|
abstract protected function getCollator($locale);
|
||||||
|
}
|
109
src/Symfony/Component/Intl/Tests/Collator/StubCollatorTest.php
Normal file
109
src/Symfony/Component/Intl/Tests/Collator/StubCollatorTest.php
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Tests\Collator;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Collator\StubCollator;
|
||||||
|
use Symfony\Component\Intl\Globals\StubIntlGlobals;
|
||||||
|
|
||||||
|
class StubCollatorTest extends AbstractCollatorTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testConstructorWithUnsupportedLocale()
|
||||||
|
{
|
||||||
|
new StubCollator('pt_BR');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testCompare()
|
||||||
|
{
|
||||||
|
$collator = $this->getCollator('en');
|
||||||
|
$collator->compare('a', 'b');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testGetAttribute()
|
||||||
|
{
|
||||||
|
$collator = $this->getCollator('en');
|
||||||
|
$collator->getAttribute(StubCollator::NUMERIC_COLLATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetErrorCode()
|
||||||
|
{
|
||||||
|
$collator = $this->getCollator('en');
|
||||||
|
$this->assertEquals(StubIntlGlobals::U_ZERO_ERROR, $collator->getErrorCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetErrorMessage()
|
||||||
|
{
|
||||||
|
$collator = $this->getCollator('en');
|
||||||
|
$this->assertEquals('U_ZERO_ERROR', $collator->getErrorMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetLocale()
|
||||||
|
{
|
||||||
|
$collator = $this->getCollator('en');
|
||||||
|
$this->assertEquals('en', $collator->getLocale());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testGetSortKey()
|
||||||
|
{
|
||||||
|
$collator = $this->getCollator('en');
|
||||||
|
$collator->getSortKey('Hello');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testGetStrength()
|
||||||
|
{
|
||||||
|
$collator = $this->getCollator('en');
|
||||||
|
$collator->getStrength();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testSetAttribute()
|
||||||
|
{
|
||||||
|
$collator = $this->getCollator('en');
|
||||||
|
$collator->setAttribute(StubCollator::NUMERIC_COLLATION, StubCollator::ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testSetStrength()
|
||||||
|
{
|
||||||
|
$collator = $this->getCollator('en');
|
||||||
|
$collator->setStrength(StubCollator::PRIMARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStaticCreate()
|
||||||
|
{
|
||||||
|
$collator = StubCollator::create('en');
|
||||||
|
$this->assertInstanceOf('Symfony\Component\Intl\Collator\StubCollator', $collator);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCollator($locale)
|
||||||
|
{
|
||||||
|
return new StubCollator($locale);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Tests\Collator\Verification;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Locale;
|
||||||
|
use Symfony\Component\Intl\Tests\Collator\AbstractCollatorTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that {@link AbstractCollatorTest} matches the behavior of the
|
||||||
|
* {@link \Collator} class in a specific version of ICU.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class CollatorTest extends AbstractCollatorTest
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->skipIfIntlExtensionNotLoaded();
|
||||||
|
$this->skipIfInsufficientIcuVersion();
|
||||||
|
|
||||||
|
parent::setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCollator($locale)
|
||||||
|
{
|
||||||
|
return new \Collator($locale);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,965 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Tests\DateFormatter;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\DateFormatter\StubIntlDateFormatter;
|
||||||
|
use Symfony\Component\Intl\Globals\StubIntlGlobals;
|
||||||
|
use Symfony\Component\Intl\Intl;
|
||||||
|
use Symfony\Component\Intl\Tests\IntlTestCase;
|
||||||
|
use Symfony\Component\Intl\Util\IcuVersion;
|
||||||
|
use Symfony\Component\Intl\Util\Version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test case for IntlDateFormatter implementations.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
abstract class AbstractIntlDateFormatterTest extends IntlTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* When a time zone is not specified, it uses the system default however it returns null in the getter method
|
||||||
|
* @covers Symfony\Component\Intl\Stub\StubIntlDateFormatter::getTimeZoneId
|
||||||
|
* @covers Symfony\Component\Intl\Stub\StubIntlDateFormatter::setTimeZoneId
|
||||||
|
* @see StubIntlDateFormatterTest::testDefaultTimeZoneIntl()
|
||||||
|
*/
|
||||||
|
public function testConstructorDefaultTimeZone()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
|
||||||
|
|
||||||
|
// In PHP 5.5 default timezone depends on `date_default_timezone_get()` method
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
$this->assertEquals(date_default_timezone_get(), $formatter->getTimeZoneId());
|
||||||
|
} else {
|
||||||
|
$this->assertNull($formatter->getTimeZoneId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider formatProvider
|
||||||
|
*/
|
||||||
|
public function testFormat($pattern, $timestamp, $expected)
|
||||||
|
{
|
||||||
|
$errorCode = StubIntlGlobals::U_ZERO_ERROR;
|
||||||
|
$errorMessage = 'U_ZERO_ERROR';
|
||||||
|
|
||||||
|
$formatter = $this->getDefaultDateFormatter($pattern);
|
||||||
|
$this->assertSame($expected, $formatter->format($timestamp));
|
||||||
|
$this->assertIsIntlSuccess($formatter, $errorMessage, $errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function formatProvider()
|
||||||
|
{
|
||||||
|
$formatData = array(
|
||||||
|
/* general */
|
||||||
|
array('y-M-d', 0, '1970-1-1'),
|
||||||
|
array("EEE, MMM d, ''yy", 0, "Thu, Jan 1, '70"),
|
||||||
|
array('h:mm a', 0, '12:00 AM'),
|
||||||
|
array('yyyyy.MMMM.dd hh:mm aaa', 0, '01970.January.01 12:00 AM'),
|
||||||
|
|
||||||
|
/* escaping */
|
||||||
|
array("'M'", 0, 'M'),
|
||||||
|
array("'yy'", 0, 'yy'),
|
||||||
|
array("'''yy'", 0, "'yy"),
|
||||||
|
array("''y", 0, "'1970"),
|
||||||
|
array("''yy", 0, "'70"),
|
||||||
|
array("H 'o'' clock'", 0, "0 o' clock"),
|
||||||
|
|
||||||
|
/* month */
|
||||||
|
array('M', 0, '1'),
|
||||||
|
array('MM', 0, '01'),
|
||||||
|
array('MMM', 0, 'Jan'),
|
||||||
|
array('MMMM', 0, 'January'),
|
||||||
|
array('MMMMM', 0, 'J'),
|
||||||
|
array('MMMMMM', 0, '000001'),
|
||||||
|
|
||||||
|
array('L', 0, '1'),
|
||||||
|
array('LL', 0, '01'),
|
||||||
|
array('LLL', 0, 'Jan'),
|
||||||
|
array('LLLL', 0, 'January'),
|
||||||
|
array('LLLLL', 0, 'J'),
|
||||||
|
array('LLLLLL', 0, '000001'),
|
||||||
|
|
||||||
|
/* year */
|
||||||
|
array('y', 0, '1970'),
|
||||||
|
array('yy', 0, '70'),
|
||||||
|
array('yyy', 0, '1970'),
|
||||||
|
array('yyyy', 0, '1970'),
|
||||||
|
array('yyyyy', 0, '01970'),
|
||||||
|
array('yyyyyy', 0, '001970'),
|
||||||
|
|
||||||
|
/* day */
|
||||||
|
array('d', 0, '1'),
|
||||||
|
array('dd', 0, '01'),
|
||||||
|
array('ddd', 0, '001'),
|
||||||
|
|
||||||
|
/* quarter */
|
||||||
|
array('Q', 0, '1'),
|
||||||
|
array('QQ', 0, '01'),
|
||||||
|
array('QQQ', 0, 'Q1'),
|
||||||
|
array('QQQQ', 0, '1st quarter'),
|
||||||
|
array('QQQQQ', 0, '1st quarter'),
|
||||||
|
|
||||||
|
array('q', 0, '1'),
|
||||||
|
array('qq', 0, '01'),
|
||||||
|
array('qqq', 0, 'Q1'),
|
||||||
|
array('qqqq', 0, '1st quarter'),
|
||||||
|
array('qqqqq', 0, '1st quarter'),
|
||||||
|
|
||||||
|
// 4 months
|
||||||
|
array('Q', 7776000, '2'),
|
||||||
|
array('QQ', 7776000, '02'),
|
||||||
|
array('QQQ', 7776000, 'Q2'),
|
||||||
|
array('QQQQ', 7776000, '2nd quarter'),
|
||||||
|
|
||||||
|
// 7 months
|
||||||
|
array('QQQQ', 15638400, '3rd quarter'),
|
||||||
|
|
||||||
|
// 10 months
|
||||||
|
array('QQQQ', 23587200, '4th quarter'),
|
||||||
|
|
||||||
|
/* 12-hour (1-12) */
|
||||||
|
array('h', 0, '12'),
|
||||||
|
array('hh', 0, '12'),
|
||||||
|
array('hhh', 0, '012'),
|
||||||
|
|
||||||
|
array('h', 1, '12'),
|
||||||
|
array('h', 3600, '1'),
|
||||||
|
array('h', 43200, '12'), // 12 hours
|
||||||
|
|
||||||
|
/* day of year */
|
||||||
|
array('D', 0, '1'),
|
||||||
|
array('D', 86400, '2'), // 1 day
|
||||||
|
array('D', 31536000, '1'), // 1 year
|
||||||
|
array('D', 31622400, '2'), // 1 year + 1 day
|
||||||
|
|
||||||
|
/* day of week */
|
||||||
|
array('E', 0, 'Thu'),
|
||||||
|
array('EE', 0, 'Thu'),
|
||||||
|
array('EEE', 0, 'Thu'),
|
||||||
|
array('EEEE', 0, 'Thursday'),
|
||||||
|
array('EEEEE', 0, 'T'),
|
||||||
|
array('EEEEEE', 0, 'Thu'),
|
||||||
|
|
||||||
|
array('E', 1296540000, 'Tue'), // 2011-02-01
|
||||||
|
array('E', 1296950400, 'Sun'), // 2011-02-06
|
||||||
|
|
||||||
|
/* am/pm marker */
|
||||||
|
array('a', 0, 'AM'),
|
||||||
|
array('aa', 0, 'AM'),
|
||||||
|
array('aaa', 0, 'AM'),
|
||||||
|
array('aaaa', 0, 'AM'),
|
||||||
|
|
||||||
|
// 12 hours
|
||||||
|
array('a', 43200, 'PM'),
|
||||||
|
array('aa', 43200, 'PM'),
|
||||||
|
array('aaa', 43200, 'PM'),
|
||||||
|
array('aaaa', 43200, 'PM'),
|
||||||
|
|
||||||
|
/* 24-hour (0-23) */
|
||||||
|
array('H', 0, '0'),
|
||||||
|
array('HH', 0, '00'),
|
||||||
|
array('HHH', 0, '000'),
|
||||||
|
|
||||||
|
array('H', 1, '0'),
|
||||||
|
array('H', 3600, '1'),
|
||||||
|
array('H', 43200, '12'),
|
||||||
|
array('H', 46800, '13'),
|
||||||
|
|
||||||
|
/* 24-hour (1-24) */
|
||||||
|
array('k', 0, '24'),
|
||||||
|
array('kk', 0, '24'),
|
||||||
|
array('kkk', 0, '024'),
|
||||||
|
|
||||||
|
array('k', 1, '24'),
|
||||||
|
array('k', 3600, '1'),
|
||||||
|
array('k', 43200, '12'),
|
||||||
|
array('k', 46800, '13'),
|
||||||
|
|
||||||
|
/* 12-hour (0-11) */
|
||||||
|
array('K', 0, '0'),
|
||||||
|
array('KK', 0, '00'),
|
||||||
|
array('KKK', 0, '000'),
|
||||||
|
|
||||||
|
array('K', 1, '0'),
|
||||||
|
array('K', 3600, '1'),
|
||||||
|
array('K', 43200, '0'), // 12 hours
|
||||||
|
|
||||||
|
/* minute */
|
||||||
|
array('m', 0, '0'),
|
||||||
|
array('mm', 0, '00'),
|
||||||
|
array('mmm', 0, '000'),
|
||||||
|
|
||||||
|
array('m', 1, '0'),
|
||||||
|
array('m', 60, '1'),
|
||||||
|
array('m', 120, '2'),
|
||||||
|
array('m', 180, '3'),
|
||||||
|
array('m', 3600, '0'),
|
||||||
|
array('m', 3660, '1'),
|
||||||
|
array('m', 43200, '0'), // 12 hours
|
||||||
|
|
||||||
|
/* second */
|
||||||
|
array('s', 0, '0'),
|
||||||
|
array('ss', 0, '00'),
|
||||||
|
array('sss', 0, '000'),
|
||||||
|
|
||||||
|
array('s', 1, '1'),
|
||||||
|
array('s', 2, '2'),
|
||||||
|
array('s', 5, '5'),
|
||||||
|
array('s', 30, '30'),
|
||||||
|
array('s', 59, '59'),
|
||||||
|
array('s', 60, '0'),
|
||||||
|
array('s', 120, '0'),
|
||||||
|
array('s', 180, '0'),
|
||||||
|
array('s', 3600, '0'),
|
||||||
|
array('s', 3601, '1'),
|
||||||
|
array('s', 3630, '30'),
|
||||||
|
array('s', 43200, '0'), // 12 hours
|
||||||
|
);
|
||||||
|
|
||||||
|
// Timezone
|
||||||
|
if (Intl::isExtensionLoaded() && IcuVersion::compare(Intl::getIcuVersion(), '4.8', '>=')) {
|
||||||
|
// general
|
||||||
|
$formatData[] = array("yyyy.MM.dd 'at' HH:mm:ss zzz", 0, '1970.01.01 at 00:00:00 GMT');
|
||||||
|
$formatData[] = array('K:mm a, z', 0, '0:00 AM, GMT');
|
||||||
|
|
||||||
|
// timezone
|
||||||
|
$formatData[] = array('z', 0, 'GMT');
|
||||||
|
$formatData[] = array('zz', 0, 'GMT');
|
||||||
|
$formatData[] = array('zzz', 0, 'GMT');
|
||||||
|
$formatData[] = array('zzzz', 0, 'GMT');
|
||||||
|
$formatData[] = array('zzzzz', 0, 'GMT');
|
||||||
|
}
|
||||||
|
|
||||||
|
// As of PHP 5.3.4, IntlDateFormatter::format() accepts DateTime instances
|
||||||
|
if (version_compare(PHP_VERSION, '5.3.4', '>=')) {
|
||||||
|
$dateTime = new \DateTime('@0');
|
||||||
|
|
||||||
|
/* general, DateTime */
|
||||||
|
$formatData[] = array('y-M-d', $dateTime, '1970-1-1');
|
||||||
|
$formatData[] = array("EEE, MMM d, ''yy", $dateTime, "Thu, Jan 1, '70");
|
||||||
|
$formatData[] = array('h:mm a', $dateTime, '12:00 AM');
|
||||||
|
$formatData[] = array('yyyyy.MMMM.dd hh:mm aaa', $dateTime, '01970.January.01 12:00 AM');
|
||||||
|
|
||||||
|
if (Intl::isExtensionLoaded() && IcuVersion::compare(Intl::getIcuVersion(), '4.8', '>=')) {
|
||||||
|
$formatData[] = array("yyyy.MM.dd 'at' HH:mm:ss zzz", $dateTime, '1970.01.01 at 00:00:00 GMT');
|
||||||
|
$formatData[] = array('K:mm a, z', $dateTime, '0:00 AM, GMT');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $formatData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider formatErrorProvider
|
||||||
|
*/
|
||||||
|
public function testFormatIllegalArgumentError($pattern, $timestamp, $errorMessage)
|
||||||
|
{
|
||||||
|
$errorCode = StubIntlGlobals::U_ILLEGAL_ARGUMENT_ERROR;
|
||||||
|
|
||||||
|
$formatter = $this->getDefaultDateFormatter($pattern);
|
||||||
|
$this->assertFalse($formatter->format($timestamp));
|
||||||
|
$this->assertIsIntlFailure($formatter, $errorMessage, $errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function formatErrorProvider()
|
||||||
|
{
|
||||||
|
// With PHP 5.5 IntlDateFormatter accepts empty values ('0')
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
return array(
|
||||||
|
array('y-M-d', 'foobar', 'datefmt_format: string \'foobar\' is not numeric, which would be required for it to be a valid date: U_ILLEGAL_ARGUMENT_ERROR')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = 'datefmt_format: takes either an array or an integer timestamp value : U_ILLEGAL_ARGUMENT_ERROR';
|
||||||
|
|
||||||
|
if (version_compare(PHP_VERSION, '5.3.4', '>=')) {
|
||||||
|
$message = 'datefmt_format: takes either an array or an integer timestamp value or a DateTime object: U_ILLEGAL_ARGUMENT_ERROR';
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
array('y-M-d', '0', $message),
|
||||||
|
array('y-M-d', 'foobar', $message),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider formatWithTimezoneProvider
|
||||||
|
*/
|
||||||
|
public function testFormatWithTimezone($timestamp, $timezone, $expected)
|
||||||
|
{
|
||||||
|
$pattern = 'yyyy-MM-dd HH:mm:ss';
|
||||||
|
$formatter = $this->getDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT, $timezone, StubIntlDateFormatter::GREGORIAN, $pattern);
|
||||||
|
$this->assertSame($expected, $formatter->format($timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function formatWithTimezoneProvider()
|
||||||
|
{
|
||||||
|
$data = array(
|
||||||
|
array(0, 'UTC', '1970-01-01 00:00:00'),
|
||||||
|
array(0, 'GMT', '1970-01-01 00:00:00'),
|
||||||
|
array(0, 'GMT-03:00', '1969-12-31 21:00:00'),
|
||||||
|
array(0, 'GMT+03:00', '1970-01-01 03:00:00'),
|
||||||
|
array(0, 'Europe/Zurich', '1970-01-01 01:00:00'),
|
||||||
|
array(0, 'Europe/Paris', '1970-01-01 01:00:00'),
|
||||||
|
array(0, 'Africa/Cairo', '1970-01-01 02:00:00'),
|
||||||
|
array(0, 'Africa/Casablanca', '1970-01-01 00:00:00'),
|
||||||
|
array(0, 'Africa/Djibouti', '1970-01-01 03:00:00'),
|
||||||
|
array(0, 'Africa/Johannesburg', '1970-01-01 02:00:00'),
|
||||||
|
array(0, 'America/Antigua', '1969-12-31 20:00:00'),
|
||||||
|
array(0, 'America/Toronto', '1969-12-31 19:00:00'),
|
||||||
|
array(0, 'America/Vancouver', '1969-12-31 16:00:00'),
|
||||||
|
array(0, 'Asia/Aqtau', '1970-01-01 05:00:00'),
|
||||||
|
array(0, 'Asia/Bangkok', '1970-01-01 07:00:00'),
|
||||||
|
array(0, 'Asia/Dubai', '1970-01-01 04:00:00'),
|
||||||
|
array(0, 'Australia/Brisbane', '1970-01-01 10:00:00'),
|
||||||
|
array(0, 'Australia/Eucla', '1970-01-01 08:45:00'),
|
||||||
|
array(0, 'Australia/Melbourne', '1970-01-01 10:00:00'),
|
||||||
|
array(0, 'Europe/Berlin', '1970-01-01 01:00:00'),
|
||||||
|
array(0, 'Europe/Dublin', '1970-01-01 01:00:00'),
|
||||||
|
array(0, 'Europe/Warsaw', '1970-01-01 01:00:00'),
|
||||||
|
array(0, 'Pacific/Fiji', '1970-01-01 12:00:00'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// As of PHP 5.5, intl ext no longer fallbacks invalid time zones to UTC
|
||||||
|
if (!version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
// When time zone not exists, uses UTC by default
|
||||||
|
$data[] = array(0, 'Foo/Bar', '1970-01-01 00:00:00');
|
||||||
|
$data[] = array(0, 'UTC+04:30', '1970-01-01 00:00:00');
|
||||||
|
$data[] = array(0, 'UTC+04:AA', '1970-01-01 00:00:00');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFormatWithGmtTimezone()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter('zzzz');
|
||||||
|
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
$formatter->setTimeZone('GMT+03:00');
|
||||||
|
} else {
|
||||||
|
$formatter->setTimeZoneId('GMT+03:00');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals('GMT+03:00', $formatter->format(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFormatWithGmtTimeZoneAndMinutesOffset()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter('zzzz');
|
||||||
|
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
$formatter->setTimeZone('GMT+00:30');
|
||||||
|
} else {
|
||||||
|
$formatter->setTimeZoneId('GMT+00:30');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals('GMT+00:30', $formatter->format(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFormatWithNonStandardTimezone()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter('zzzz');
|
||||||
|
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
$formatter->setTimeZone('Pacific/Fiji');
|
||||||
|
} else {
|
||||||
|
$formatter->setTimeZoneId('Pacific/Fiji');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals('Fiji Standard Time', $formatter->format(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFormatWithConstructorTimezone()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT, 'UTC');
|
||||||
|
$formatter->setPattern('yyyy-MM-dd HH:mm:ss');
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
$this->getDateTime(0)->format('Y-m-d H:i:s'),
|
||||||
|
$formatter->format(0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFormatWithTimezoneFromEnvironmentVariable()
|
||||||
|
{
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
$this->markTestSkipped('IntlDateFormatter in PHP 5.5 no longer depends on TZ environment.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$tz = getenv('TZ');
|
||||||
|
putenv('TZ=Europe/London');
|
||||||
|
|
||||||
|
$formatter = $this->getDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
|
||||||
|
$formatter->setPattern('yyyy-MM-dd HH:mm:ss');
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
$this->getDateTime(0)->format('Y-m-d H:i:s'),
|
||||||
|
$formatter->format(0)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals('Europe/London', getenv('TZ'));
|
||||||
|
|
||||||
|
// Restores TZ.
|
||||||
|
putenv('TZ='.$tz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFormatWithTimezoneFromPhp()
|
||||||
|
{
|
||||||
|
if (!version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
$this->markTestSkipped('Only in PHP 5.5 IntlDateFormatter depends on default timezone (`date_default_timezone_get()`).');
|
||||||
|
}
|
||||||
|
|
||||||
|
$tz = date_default_timezone_get();
|
||||||
|
date_default_timezone_set('Europe/London');
|
||||||
|
|
||||||
|
$formatter = $this->getDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
|
||||||
|
$formatter->setPattern('yyyy-MM-dd HH:mm:ss');
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
$this->getDateTime(0)->format('Y-m-d H:i:s'),
|
||||||
|
$formatter->format(0)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals('Europe/London', date_default_timezone_get());
|
||||||
|
|
||||||
|
// Restores TZ.
|
||||||
|
date_default_timezone_set($tz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dateAndTimeTypeProvider
|
||||||
|
*/
|
||||||
|
public function testDateAndTimeType($timestamp, $datetype, $timetype, $expected)
|
||||||
|
{
|
||||||
|
$formatter = $this->getDateFormatter('en', $datetype, $timetype, 'UTC');
|
||||||
|
$this->assertSame($expected, $formatter->format($timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dateAndTimeTypeProvider()
|
||||||
|
{
|
||||||
|
$data = array(
|
||||||
|
array(0, StubIntlDateFormatter::FULL, StubIntlDateFormatter::NONE, 'Thursday, January 1, 1970'),
|
||||||
|
array(0, StubIntlDateFormatter::LONG, StubIntlDateFormatter::NONE, 'January 1, 1970'),
|
||||||
|
array(0, StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::NONE, 'Jan 1, 1970'),
|
||||||
|
array(0, StubIntlDateFormatter::SHORT, StubIntlDateFormatter::NONE, '1/1/70'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Intl::isExtensionLoaded() && IcuVersion::compare(Intl::getIcuVersion(), '4.8', '>=')) {
|
||||||
|
$data[] = array(0, StubIntlDateFormatter::NONE, StubIntlDateFormatter::FULL, '12:00:00 AM GMT');
|
||||||
|
$data[] = array(0, StubIntlDateFormatter::NONE, StubIntlDateFormatter::LONG, '12:00:00 AM GMT');
|
||||||
|
}
|
||||||
|
|
||||||
|
$data[] = array(0, StubIntlDateFormatter::NONE, StubIntlDateFormatter::MEDIUM, '12:00:00 AM');
|
||||||
|
$data[] = array(0, StubIntlDateFormatter::NONE, StubIntlDateFormatter::SHORT, '12:00 AM');
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetCalendar()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
$this->assertEquals(StubIntlDateFormatter::GREGORIAN, $formatter->getCalendar());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetDateType()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDateFormatter('en', StubIntlDateFormatter::FULL, StubIntlDateFormatter::NONE);
|
||||||
|
$this->assertEquals(StubIntlDateFormatter::FULL, $formatter->getDateType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetLocale()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
$this->assertEquals('en', $formatter->getLocale());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetPattern()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDateFormatter('en', StubIntlDateFormatter::FULL, StubIntlDateFormatter::NONE, 'UTC', StubIntlDateFormatter::GREGORIAN, 'yyyy-MM-dd');
|
||||||
|
$this->assertEquals('yyyy-MM-dd', $formatter->getPattern());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetTimeType()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDateFormatter('en', StubIntlDateFormatter::NONE, StubIntlDateFormatter::FULL);
|
||||||
|
$this->assertEquals(StubIntlDateFormatter::FULL, $formatter->getTimeType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider parseProvider
|
||||||
|
*/
|
||||||
|
public function testParse($pattern, $value, $expected)
|
||||||
|
{
|
||||||
|
$errorCode = StubIntlGlobals::U_ZERO_ERROR;
|
||||||
|
$errorMessage = 'U_ZERO_ERROR';
|
||||||
|
|
||||||
|
$formatter = $this->getDefaultDateFormatter($pattern);
|
||||||
|
$this->assertSame($expected, $formatter->parse($value));
|
||||||
|
$this->assertIsIntlSuccess($formatter, $errorMessage, $errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseProvider()
|
||||||
|
{
|
||||||
|
return array_merge(
|
||||||
|
$this->parseYearProvider(),
|
||||||
|
$this->parseQuarterProvider(),
|
||||||
|
$this->parseMonthProvider(),
|
||||||
|
$this->parseStandaloneMonthProvider(),
|
||||||
|
$this->parseDayProvider(),
|
||||||
|
$this->parseDayOfWeekProvider(),
|
||||||
|
$this->parseDayOfYearProvider(),
|
||||||
|
$this->parseHour12ClockOneBasedProvider(),
|
||||||
|
$this->parseHour12ClockZeroBasedProvider(),
|
||||||
|
$this->parseHour24ClockOneBasedProvider(),
|
||||||
|
$this->parseHour24ClockZeroBasedProvider(),
|
||||||
|
$this->parseMinuteProvider(),
|
||||||
|
$this->parseSecondProvider(),
|
||||||
|
$this->parseTimezoneProvider(),
|
||||||
|
$this->parseAmPmProvider(),
|
||||||
|
$this->parseStandaloneAmPmProvider(),
|
||||||
|
$this->parseRegexMetaCharsProvider(),
|
||||||
|
$this->parseQuoteCharsProvider(),
|
||||||
|
$this->parseDashSlashProvider()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseYearProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('y-M-d', '1970-1-1', 0),
|
||||||
|
array('yy-M-d', '70-1-1', 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseQuarterProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('Q', '1', 0),
|
||||||
|
array('QQ', '01', 0),
|
||||||
|
array('QQQ', 'Q1', 0),
|
||||||
|
array('QQQQ', '1st quarter', 0),
|
||||||
|
array('QQQQQ', '1st quarter', 0),
|
||||||
|
|
||||||
|
array('Q', '2', 7776000),
|
||||||
|
array('QQ', '02', 7776000),
|
||||||
|
array('QQQ', 'Q2', 7776000),
|
||||||
|
array('QQQQ', '2nd quarter', 7776000),
|
||||||
|
array('QQQQQ', '2nd quarter', 7776000),
|
||||||
|
|
||||||
|
array('q', '1', 0),
|
||||||
|
array('qq', '01', 0),
|
||||||
|
array('qqq', 'Q1', 0),
|
||||||
|
array('qqqq', '1st quarter', 0),
|
||||||
|
array('qqqqq', '1st quarter', 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseMonthProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('y-M-d', '1970-1-1', 0),
|
||||||
|
array('y-MMM-d', '1970-Jan-1', 0),
|
||||||
|
array('y-MMMM-d', '1970-January-1', 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseStandaloneMonthProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('y-L-d', '1970-1-1', 0),
|
||||||
|
array('y-LLL-d', '1970-Jan-1', 0),
|
||||||
|
array('y-LLLL-d', '1970-January-1', 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseDayProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('y-M-d', '1970-1-1', 0),
|
||||||
|
array('y-M-dd', '1970-1-01', 0),
|
||||||
|
array('y-M-ddd', '1970-1-001', 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseDayOfWeekProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('E', 'Thu', 0),
|
||||||
|
array('EE', 'Thu', 0),
|
||||||
|
array('EEE', 'Thu', 0),
|
||||||
|
array('EEEE', 'Thursday', 0),
|
||||||
|
array('EEEEE', 'T', 432000),
|
||||||
|
array('EEEEEE', 'Thu', 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseDayOfYearProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('D', '1', 0),
|
||||||
|
array('D', '2', 86400),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseHour12ClockOneBasedProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// 12 hours (1-12)
|
||||||
|
array('y-M-d h', '1970-1-1 1', 3600),
|
||||||
|
array('y-M-d h', '1970-1-1 10', 36000),
|
||||||
|
array('y-M-d hh', '1970-1-1 11', 39600),
|
||||||
|
array('y-M-d hh', '1970-1-1 12', 0),
|
||||||
|
array('y-M-d hh a', '1970-1-1 0 AM', 0),
|
||||||
|
array('y-M-d hh a', '1970-1-1 1 AM', 3600),
|
||||||
|
array('y-M-d hh a', '1970-1-1 10 AM', 36000),
|
||||||
|
array('y-M-d hh a', '1970-1-1 11 AM', 39600),
|
||||||
|
array('y-M-d hh a', '1970-1-1 12 AM', 0),
|
||||||
|
array('y-M-d hh a', '1970-1-1 23 AM', 82800),
|
||||||
|
array('y-M-d hh a', '1970-1-1 24 AM', 86400),
|
||||||
|
array('y-M-d hh a', '1970-1-1 0 PM', 43200),
|
||||||
|
array('y-M-d hh a', '1970-1-1 1 PM', 46800),
|
||||||
|
array('y-M-d hh a', '1970-1-1 10 PM', 79200),
|
||||||
|
array('y-M-d hh a', '1970-1-1 11 PM', 82800),
|
||||||
|
array('y-M-d hh a', '1970-1-1 12 PM', 43200),
|
||||||
|
array('y-M-d hh a', '1970-1-1 23 PM', 126000),
|
||||||
|
array('y-M-d hh a', '1970-1-1 24 PM', 129600),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseHour12ClockZeroBasedProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// 12 hours (0-11)
|
||||||
|
array('y-M-d K', '1970-1-1 1', 3600),
|
||||||
|
array('y-M-d K', '1970-1-1 10', 36000),
|
||||||
|
array('y-M-d KK', '1970-1-1 11', 39600),
|
||||||
|
array('y-M-d KK', '1970-1-1 12', 43200),
|
||||||
|
array('y-M-d KK a', '1970-1-1 0 AM', 0),
|
||||||
|
array('y-M-d KK a', '1970-1-1 1 AM', 3600),
|
||||||
|
array('y-M-d KK a', '1970-1-1 10 AM', 36000),
|
||||||
|
array('y-M-d KK a', '1970-1-1 11 AM', 39600),
|
||||||
|
array('y-M-d KK a', '1970-1-1 12 AM', 43200),
|
||||||
|
array('y-M-d KK a', '1970-1-1 23 AM', 82800),
|
||||||
|
array('y-M-d KK a', '1970-1-1 24 AM', 86400),
|
||||||
|
array('y-M-d KK a', '1970-1-1 0 PM', 43200),
|
||||||
|
array('y-M-d KK a', '1970-1-1 1 PM', 46800),
|
||||||
|
array('y-M-d KK a', '1970-1-1 10 PM', 79200),
|
||||||
|
array('y-M-d KK a', '1970-1-1 11 PM', 82800),
|
||||||
|
array('y-M-d KK a', '1970-1-1 12 PM', 86400),
|
||||||
|
array('y-M-d KK a', '1970-1-1 23 PM', 126000),
|
||||||
|
array('y-M-d KK a', '1970-1-1 24 PM', 129600),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseHour24ClockOneBasedProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// 24 hours (1-24)
|
||||||
|
array('y-M-d k', '1970-1-1 1', 3600),
|
||||||
|
array('y-M-d k', '1970-1-1 10', 36000),
|
||||||
|
array('y-M-d kk', '1970-1-1 11', 39600),
|
||||||
|
array('y-M-d kk', '1970-1-1 12', 43200),
|
||||||
|
array('y-M-d kk', '1970-1-1 23', 82800),
|
||||||
|
array('y-M-d kk', '1970-1-1 24', 0),
|
||||||
|
array('y-M-d kk a', '1970-1-1 0 AM', 0),
|
||||||
|
array('y-M-d kk a', '1970-1-1 1 AM', 0),
|
||||||
|
array('y-M-d kk a', '1970-1-1 10 AM', 0),
|
||||||
|
array('y-M-d kk a', '1970-1-1 11 AM', 0),
|
||||||
|
array('y-M-d kk a', '1970-1-1 12 AM', 0),
|
||||||
|
array('y-M-d kk a', '1970-1-1 23 AM', 0),
|
||||||
|
array('y-M-d kk a', '1970-1-1 24 AM', 0),
|
||||||
|
array('y-M-d kk a', '1970-1-1 0 PM', 43200),
|
||||||
|
array('y-M-d kk a', '1970-1-1 1 PM', 43200),
|
||||||
|
array('y-M-d kk a', '1970-1-1 10 PM', 43200),
|
||||||
|
array('y-M-d kk a', '1970-1-1 11 PM', 43200),
|
||||||
|
array('y-M-d kk a', '1970-1-1 12 PM', 43200),
|
||||||
|
array('y-M-d kk a', '1970-1-1 23 PM', 43200),
|
||||||
|
array('y-M-d kk a', '1970-1-1 24 PM', 43200),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseHour24ClockZeroBasedProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// 24 hours (0-23)
|
||||||
|
array('y-M-d H', '1970-1-1 0', 0),
|
||||||
|
array('y-M-d H', '1970-1-1 1', 3600),
|
||||||
|
array('y-M-d H', '1970-1-1 10', 36000),
|
||||||
|
array('y-M-d HH', '1970-1-1 11', 39600),
|
||||||
|
array('y-M-d HH', '1970-1-1 12', 43200),
|
||||||
|
array('y-M-d HH', '1970-1-1 23', 82800),
|
||||||
|
array('y-M-d HH a', '1970-1-1 0 AM', 0),
|
||||||
|
array('y-M-d HH a', '1970-1-1 1 AM', 0),
|
||||||
|
array('y-M-d HH a', '1970-1-1 10 AM', 0),
|
||||||
|
array('y-M-d HH a', '1970-1-1 11 AM', 0),
|
||||||
|
array('y-M-d HH a', '1970-1-1 12 AM', 0),
|
||||||
|
array('y-M-d HH a', '1970-1-1 23 AM', 0),
|
||||||
|
array('y-M-d HH a', '1970-1-1 24 AM', 0),
|
||||||
|
array('y-M-d HH a', '1970-1-1 0 PM', 43200),
|
||||||
|
array('y-M-d HH a', '1970-1-1 1 PM', 43200),
|
||||||
|
array('y-M-d HH a', '1970-1-1 10 PM', 43200),
|
||||||
|
array('y-M-d HH a', '1970-1-1 11 PM', 43200),
|
||||||
|
array('y-M-d HH a', '1970-1-1 12 PM', 43200),
|
||||||
|
array('y-M-d HH a', '1970-1-1 23 PM', 43200),
|
||||||
|
array('y-M-d HH a', '1970-1-1 24 PM', 43200),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseMinuteProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('y-M-d HH:m', '1970-1-1 0:1', 60),
|
||||||
|
array('y-M-d HH:mm', '1970-1-1 0:10', 600),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseSecondProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('y-M-d HH:mm:s', '1970-1-1 00:01:1', 61),
|
||||||
|
array('y-M-d HH:mm:ss', '1970-1-1 00:01:10', 70),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseTimezoneProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-03:00', 10800),
|
||||||
|
array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-04:00', 14400),
|
||||||
|
array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-00:00', 0),
|
||||||
|
array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT+03:00', -10800),
|
||||||
|
array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT+04:00', -14400),
|
||||||
|
array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-0300', 10800),
|
||||||
|
array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT+0300', -10800),
|
||||||
|
|
||||||
|
// a previous timezone parsing should not change the timezone for the next parsing
|
||||||
|
array('y-M-d HH:mm:ss', '1970-1-1 00:00:00', 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseAmPmProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// AM/PM (already covered by hours tests)
|
||||||
|
array('y-M-d HH:mm:ss a', '1970-1-1 00:00:00 AM', 0),
|
||||||
|
array('y-M-d HH:mm:ss a', '1970-1-1 00:00:00 PM', 43200),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseStandaloneAmPmProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('a', 'AM', 0),
|
||||||
|
array('a', 'PM', 43200),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseRegexMetaCharsProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// regexp meta chars in the pattern string
|
||||||
|
array('y[M-d', '1970[1-1', 0),
|
||||||
|
array('y[M/d', '1970[1/1', 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseQuoteCharsProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array("'M'", 'M', 0),
|
||||||
|
array("'yy'", 'yy', 0),
|
||||||
|
array("'''yy'", "'yy", 0),
|
||||||
|
array("''y", "'1970", 0),
|
||||||
|
array("H 'o'' clock'", "0 o' clock", 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseDashSlashProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('y-M-d', '1970/1/1', 0),
|
||||||
|
array('yy-M-d', '70/1/1', 0),
|
||||||
|
array('y/M/d', '1970-1-1', 0),
|
||||||
|
array('yy/M/d', '70-1-1', 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider parseErrorProvider
|
||||||
|
*/
|
||||||
|
public function testParseError($pattern, $value)
|
||||||
|
{
|
||||||
|
$errorCode = StubIntlGlobals::U_PARSE_ERROR;
|
||||||
|
$errorMessage = 'Date parsing failed: U_PARSE_ERROR';
|
||||||
|
|
||||||
|
$formatter = $this->getDefaultDateFormatter($pattern);
|
||||||
|
$this->assertFalse($formatter->parse($value));
|
||||||
|
$this->assertIsIntlFailure($formatter, $errorMessage, $errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseErrorProvider()
|
||||||
|
{
|
||||||
|
$data = array(
|
||||||
|
// 1 char month
|
||||||
|
array('y-MMMMM-d', '1970-J-1'),
|
||||||
|
array('y-MMMMM-d', '1970-S-1'),
|
||||||
|
|
||||||
|
// standalone 1 char month
|
||||||
|
array('y-LLLLL-d', '1970-J-1'),
|
||||||
|
array('y-LLLLL-d', '1970-S-1'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!Intl::isExtensionLoaded() || IcuVersion::compare(Intl::getIcuVersion(), '4.8', '<')) {
|
||||||
|
$data[] = array('y-M-d', '1970/1/1');
|
||||||
|
$data[] = array('yy-M-d', '70/1/1');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* https://github.com/symfony/symfony/issues/4242
|
||||||
|
*/
|
||||||
|
public function testParseAfterError()
|
||||||
|
{
|
||||||
|
$this->testParseError('y-MMMMM-d', '1970-J-1');
|
||||||
|
$this->testParse('y-M-d', '1970-1-1', 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testParseWithNullPositionValue()
|
||||||
|
{
|
||||||
|
$position = null;
|
||||||
|
$formatter = $this->getDefaultDateFormatter('y');
|
||||||
|
$this->assertSame(0, $formatter->parse('1970', $position));
|
||||||
|
$this->assertNull($position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetPattern()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
$formatter->setPattern('yyyy-MM-dd');
|
||||||
|
$this->assertEquals('yyyy-MM-dd', $formatter->getPattern());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers Symfony\Component\Intl\Stub\StubIntlDateFormatter::getTimeZoneId
|
||||||
|
* @dataProvider setTimeZoneIdProvider
|
||||||
|
*/
|
||||||
|
public function testSetTimeZoneId($timeZoneId, $expectedTimeZoneId)
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
$formatter->setTimeZone($timeZoneId);
|
||||||
|
} else {
|
||||||
|
$formatter->setTimeZoneId($timeZoneId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals($expectedTimeZoneId, $formatter->getTimeZoneId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTimeZoneIdProvider()
|
||||||
|
{
|
||||||
|
$data = array(
|
||||||
|
array('UTC', 'UTC'),
|
||||||
|
array('GMT', 'GMT'),
|
||||||
|
array('GMT-03:00', 'GMT-03:00'),
|
||||||
|
array('Europe/Zurich', 'Europe/Zurich'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// When time zone not exists, uses UTC by default
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
$data[] = array('GMT-0300', 'UTC');
|
||||||
|
$data[] = array('Foo/Bar', 'UTC');
|
||||||
|
$data[] = array('GMT+00:AA', 'UTC');
|
||||||
|
$data[] = array('GMT+00AA', 'UTC');
|
||||||
|
} else {
|
||||||
|
$data[] = array('GMT-0300', 'GMT-0300');
|
||||||
|
$data[] = array('Foo/Bar', 'Foo/Bar');
|
||||||
|
$data[] = array('GMT+00:AA', 'GMT+00:AA');
|
||||||
|
$data[] = array('GMT+00AA', 'GMT+00AA');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getDefaultDateFormatter($pattern = null)
|
||||||
|
{
|
||||||
|
return $this->getDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT, 'UTC', StubIntlDateFormatter::GREGORIAN, $pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getDateTime($timestamp = null)
|
||||||
|
{
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||||
|
$timeZone = date_default_timezone_get();
|
||||||
|
} else {
|
||||||
|
$timeZone = getenv('TZ') ?: 'UTC';
|
||||||
|
}
|
||||||
|
|
||||||
|
$dateTime = new \DateTime();
|
||||||
|
$dateTime->setTimestamp(null === $timestamp ? time() : $timestamp);
|
||||||
|
$dateTime->setTimeZone(new \DateTimeZone($timeZone));
|
||||||
|
|
||||||
|
return $dateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function assertIsIntlFailure($formatter, $errorMessage, $errorCode)
|
||||||
|
{
|
||||||
|
$this->assertSame($errorMessage, $this->getIntlErrorMessage());
|
||||||
|
$this->assertSame($errorCode, $this->getIntlErrorCode());
|
||||||
|
$this->assertTrue($this->isIntlFailure($this->getIntlErrorCode()));
|
||||||
|
$this->assertSame($errorMessage, $formatter->getErrorMessage());
|
||||||
|
$this->assertSame($errorCode, $formatter->getErrorCode());
|
||||||
|
$this->assertTrue($this->isIntlFailure($formatter->getErrorCode()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function assertIsIntlSuccess($formatter, $errorMessage, $errorCode)
|
||||||
|
{
|
||||||
|
/* @var StubIntlDateFormatter $formatter */
|
||||||
|
$this->assertSame($errorMessage, $this->getIntlErrorMessage());
|
||||||
|
$this->assertSame($errorCode, $this->getIntlErrorCode());
|
||||||
|
$this->assertFalse($this->isIntlFailure($this->getIntlErrorCode()));
|
||||||
|
$this->assertSame($errorMessage, $formatter->getErrorMessage());
|
||||||
|
$this->assertSame($errorCode, $formatter->getErrorCode());
|
||||||
|
$this->assertFalse($this->isIntlFailure($formatter->getErrorCode()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $locale
|
||||||
|
* @param $datetype
|
||||||
|
* @param $timetype
|
||||||
|
* @param null $timezone
|
||||||
|
* @param int $calendar
|
||||||
|
* @param null $pattern
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
abstract protected function getDateFormatter($locale, $datetype, $timetype, $timezone = null, $calendar = StubIntlDateFormatter::GREGORIAN, $pattern = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
abstract protected function getIntlErrorMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
abstract protected function getIntlErrorCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param integer $errorCode
|
||||||
|
*
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
abstract protected function isIntlFailure($errorCode);
|
||||||
|
}
|
@ -0,0 +1,221 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Tests\DateFormatter;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\DateFormatter\StubIntlDateFormatter;
|
||||||
|
use Symfony\Component\Intl\Globals\StubIntlGlobals;
|
||||||
|
use Symfony\Component\Intl\Util\Version;
|
||||||
|
|
||||||
|
class StubIntlDateFormatterTest extends AbstractIntlDateFormatterTest
|
||||||
|
{
|
||||||
|
public function testConstructor()
|
||||||
|
{
|
||||||
|
$formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT, 'UTC', StubIntlDateFormatter::GREGORIAN, 'y-M-d');
|
||||||
|
$this->assertEquals('y-M-d', $formatter->getPattern());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testConstructorWithUnsupportedLocale()
|
||||||
|
{
|
||||||
|
new StubIntlDateFormatter('pt_BR', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStaticCreate()
|
||||||
|
{
|
||||||
|
$formatter = StubIntlDateFormatter::create('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
|
||||||
|
$this->assertInstanceOf('Symfony\Component\Intl\DateFormatter\StubIntlDateFormatter', $formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFormatWithUnsupportedTimestampArgument()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
|
||||||
|
$localtime = array(
|
||||||
|
'tm_sec' => 59,
|
||||||
|
'tm_min' => 3,
|
||||||
|
'tm_hour' => 15,
|
||||||
|
'tm_mday' => 15,
|
||||||
|
'tm_mon' => 3,
|
||||||
|
'tm_year' => 112,
|
||||||
|
'tm_wday' => 0,
|
||||||
|
'tm_yday' => 105,
|
||||||
|
'tm_isdst' => 0
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$formatter->format($localtime);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->assertInstanceOf('Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException', $e);
|
||||||
|
|
||||||
|
if (version_compare(PHP_VERSION, '5.3.4', '>=')) {
|
||||||
|
$this->assertStringEndsWith('Only integer unix timestamps and DateTime objects are supported. Please install the "intl" extension for full localization capabilities.', $e->getMessage());
|
||||||
|
} else {
|
||||||
|
$this->assertStringEndsWith('Only integer unix timestamps are supported. Please install the "intl" extension for full localization capabilities.', $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\NotImplementedException
|
||||||
|
*/
|
||||||
|
public function testFormatWithUnimplementedChars()
|
||||||
|
{
|
||||||
|
$pattern = 'Y';
|
||||||
|
$formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT, 'UTC', StubIntlDateFormatter::GREGORIAN, $pattern);
|
||||||
|
$formatter->format(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\NotImplementedException
|
||||||
|
*/
|
||||||
|
public function testFormatWithNonIntegerTimestamp()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
$formatter->format(array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetErrorCode()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
$this->assertEquals(StubIntlGlobals::getErrorCode(), $formatter->getErrorCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetErrorMessage()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
$this->assertEquals(StubIntlGlobals::getErrorMessage(), $formatter->getErrorMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsLenient()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
$this->assertFalse($formatter->isLenient());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testLocaltime()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
$formatter->localtime('Wednesday, December 31, 1969 4:00:00 PM PT');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testParseWithNotNullPositionValue()
|
||||||
|
{
|
||||||
|
$position = 0;
|
||||||
|
$formatter = $this->getDefaultDateFormatter('y');
|
||||||
|
$this->assertSame(0, $formatter->parse('1970', $position));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testSetCalendar()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
$formatter->setCalendar(StubIntlDateFormatter::GREGORIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException
|
||||||
|
*/
|
||||||
|
public function testSetLenient()
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter();
|
||||||
|
$formatter->setLenient(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\NotImplementedException
|
||||||
|
*/
|
||||||
|
public function testFormatWithGmtTimeZoneAndMinutesOffset()
|
||||||
|
{
|
||||||
|
parent::testFormatWithGmtTimeZoneAndMinutesOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Intl\Exception\NotImplementedException
|
||||||
|
*/
|
||||||
|
public function testFormatWithNonStandardTimezone()
|
||||||
|
{
|
||||||
|
parent::testFormatWithNonStandardTimezone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseStandaloneAmPmProvider()
|
||||||
|
{
|
||||||
|
return $this->notImplemented(parent::parseStandaloneAmPmProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseDayOfWeekProvider()
|
||||||
|
{
|
||||||
|
return $this->notImplemented(parent::parseDayOfWeekProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseDayOfYearProvider()
|
||||||
|
{
|
||||||
|
return $this->notImplemented(parent::parseDayOfYearProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseQuarterProvider()
|
||||||
|
{
|
||||||
|
return $this->notImplemented(parent::parseQuarterProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getDateFormatter($locale, $datetype, $timetype, $timezone = null, $calendar = StubIntlDateFormatter::GREGORIAN, $pattern = null)
|
||||||
|
{
|
||||||
|
return new StubIntlDateFormatter($locale, $datetype, $timetype, $timezone, $calendar, $pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getIntlErrorMessage()
|
||||||
|
{
|
||||||
|
return StubIntlGlobals::getErrorMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getIntlErrorCode()
|
||||||
|
{
|
||||||
|
return StubIntlGlobals::getErrorCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isIntlFailure($errorCode)
|
||||||
|
{
|
||||||
|
return StubIntlGlobals::isFailure($errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just to document the differences between the stub and the intl
|
||||||
|
* implementations. The intl can parse any of the tested formats alone. The
|
||||||
|
* stub does not implement them as it would be needed to add more
|
||||||
|
* abstraction, passing more context to the transformers objects. Any of the
|
||||||
|
* formats are ignored alone or with date/time data (years, months, days,
|
||||||
|
* hours, minutes and seconds).
|
||||||
|
*
|
||||||
|
* Also in intl, format like 'ss E' for '10 2' (2nd day of year
|
||||||
|
* + 10 seconds) are added, then we have 86,400 seconds (24h * 60min * 60s)
|
||||||
|
* + 10 seconds
|
||||||
|
*
|
||||||
|
* @param array $dataSets
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function notImplemented(array $dataSets)
|
||||||
|
{
|
||||||
|
return array_map(function ($row) {
|
||||||
|
return array($row[0], $row[1], 0);
|
||||||
|
}, $dataSets);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Tests\DateFormatter\Verification;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\DateFormatter\StubIntlDateFormatter;
|
||||||
|
use Symfony\Component\Intl\Tests\DateFormatter\AbstractIntlDateFormatterTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that {@link AbstractIntlDateFormatterTest} matches the behavior of
|
||||||
|
* the {@link \IntlDateFormatter} class in a specific version of ICU.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class IntlDateFormatterTest extends AbstractIntlDateFormatterTest
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->skipIfIntlExtensionNotLoaded();
|
||||||
|
$this->skipIfInsufficientIcuVersion();
|
||||||
|
|
||||||
|
parent::setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It seems IntlDateFormatter caches the timezone id when not explicitly set via constructor or by the
|
||||||
|
* setTimeZoneId() method. Since testFormatWithDefaultTimezoneIntl() runs using the default environment
|
||||||
|
* time zone, this test would use it too if not running in a separated process.
|
||||||
|
*
|
||||||
|
* @runInSeparateProcess
|
||||||
|
*/
|
||||||
|
public function testFormatWithTimezoneFromEnvironmentVariable()
|
||||||
|
{
|
||||||
|
parent::testFormatWithTimezoneFromEnvironmentVariable();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getDateFormatter($locale, $datetype, $timetype, $timezone = null, $calendar = StubIntlDateFormatter::GREGORIAN, $pattern = null)
|
||||||
|
{
|
||||||
|
return new \IntlDateFormatter($locale, $datetype, $timetype, $timezone, $calendar, $pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getIntlErrorMessage()
|
||||||
|
{
|
||||||
|
return intl_get_error_message();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getIntlErrorCode()
|
||||||
|
{
|
||||||
|
return intl_get_error_code();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isIntlFailure($errorCode)
|
||||||
|
{
|
||||||
|
return intl_is_failure($errorCode);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Intl\Tests\Globals;
|
||||||
|
|
||||||
|
use Symfony\Component\Intl\Tests\IntlTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test case for intl function implementations.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
abstract class AbstractIntlGlobalsTest extends IntlTestCase
|
||||||
|
{
|
||||||
|
public function errorNameProvider()
|
||||||
|
{
|
||||||
|
return array (
|
||||||
|
array(-129, '[BOGUS UErrorCode]'),
|
||||||
|
array(0, 'U_ZERO_ERROR'),
|
||||||
|
array(1, 'U_ILLEGAL_ARGUMENT_ERROR'),
|
||||||
|
array(9, 'U_PARSE_ERROR'),
|
||||||
|
array(129, '[BOGUS UErrorCode]'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider errorNameProvider
|
||||||
|
*/
|
||||||
|
public function testGetErrorName($errorCode, $errorName)
|
||||||
|
{
|
||||||
|
$this->assertSame($errorName, $this->getIntlErrorName($errorCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function getIntlErrorName($errorCode);
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user