1
0
Fork 0
mirror of https://github.com/wallabag/wallabag.git synced 2025-09-05 18:41:02 +00:00

twig implementation

This commit is contained in:
Nicolas Lœuillet 2013-08-03 19:26:54 +02:00
parent 2b840e0cfb
commit 4f5b44bd3b
1418 changed files with 108207 additions and 1586 deletions

View 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);
}
}

View 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\Compiler;
use Symfony\Component\Intl\Exception\RuntimeException;
/**
* Compiles .txt resource bundles to binary .res files.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class BundleCompiler implements BundleCompilerInterface
{
/**
* @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.
* @param string $envVars Optional. Environment variables to be loaded when
* running "genrb".
*
* @throws RuntimeException If the "genrb" cannot be found.
*/
public function __construct($genrb = 'genrb', $envVars = '')
{
exec('which ' . $genrb, $output, $status);
if (0 !== $status) {
throw new RuntimeException(sprintf(
'The command "%s" is not installed',
$genrb
));
}
$this->genrb = ($envVars ? $envVars . ' ' : '') . $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
));
}
}
}

View file

@ -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 BundleCompilerInterface
{
/**
* Compiles a resource bundle at the given source to the given target
* directory.
*
* @param string $sourcePath
* @param string $targetDir
*/
public function compile($sourcePath, $targetDir);
}

View file

@ -0,0 +1,94 @@
<?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($currency, $locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
return $this->readEntry($locale, array('Currencies', $currency, static::INDEX_SYMBOL));
}
/**
* {@inheritdoc}
*/
public function getCurrencyName($currency, $locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
return $this->readEntry($locale, array('Currencies', $currency, static::INDEX_NAME));
}
/**
* {@inheritdoc}
*/
public function getCurrencyNames($locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
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));
}
}

View file

@ -0,0 +1,74 @@
<?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 $currency A currency code (e.g. "EUR").
* @param string $locale Optional. The locale to return the result in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The currency symbol or NULL if not found.
*/
public function getCurrencySymbol($currency, $locale = null);
/**
* Returns the name of a currency.
*
* @param string $currency A currency code (e.g. "EUR").
* @param string $locale Optional. The locale to return the name in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The name of the currency or NULL if not found.
*/
public function getCurrencyName($currency, $locale = null);
/**
* Returns the names of all known currencies.
*
* @param string $locale Optional. The locale to return the names in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string[] A list of currency names indexed by currency codes.
*/
public function getCurrencyNames($locale = null);
/**
* 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);
}

View file

@ -0,0 +1,115 @@
<?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($lang, $region = null, $locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
if (null === ($languages = $this->readEntry($locale, array('Languages')))) {
return null;
}
// 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 = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
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($script, $lang = null, $locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
$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 = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
if (null === ($scripts = $this->readEntry($locale, array('Scripts')))) {
return array();
}
if ($scripts instanceof \Traversable) {
$scripts = iterator_to_array($scripts);
}
return $scripts;
}
}

View file

@ -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\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 $lang A language code (e.g. "en").
* @param string|null $region Optional. A region code (e.g. "US").
* @param string $locale Optional. The locale to return the name in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The name of the language or NULL if not found.
*/
public function getLanguageName($lang, $region = null, $locale = null);
/**
* Returns the names of all known languages.
*
* @param string $locale Optional. The locale to return the names in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string[] A list of language names indexed by language codes.
*/
public function getLanguageNames($locale = null);
/**
* Returns the name of a script.
*
* @param string $script A script code (e.g. "Hans").
* @param string $lang Optional. A language code (e.g. "zh").
* @param string $locale Optional. The locale to return the name in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The name of the script or NULL if not found.
*/
public function getScriptName($script, $lang = null, $locale = null);
/**
* Returns the names of all known scripts.
*
* @param string $locale Optional. The locale to return the names in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string[] A list of script names indexed by script codes.
*/
public function getScriptNames($locale = null);
}

View file

@ -0,0 +1,52 @@
<?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($ofLocale, $locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
return $this->readEntry($locale, array('Locales', $ofLocale));
}
/**
* {@inheritdoc}
*/
public function getLocaleNames($locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
if (null === ($locales = $this->readEntry($locale, array('Locales')))) {
return array();
}
if ($locales instanceof \Traversable) {
$locales = iterator_to_array($locales);
}
return $locales;
}
}

View file

@ -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\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 $ofLocale The locale to return the name of (e.g. "de_AT").
* @param string $locale Optional. The locale to return the name in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The name of the locale or NULL if not found.
*/
public function getLocaleName($ofLocale, $locale = null);
/**
* Returns the names of all known locales.
*
* @param string $locale Optional. The locale to return the names in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string[] A list of locale names indexed by locale codes.
*/
public function getLocaleNames($locale = null);
}

View file

@ -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();
}

View file

@ -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';
}
}

View file

@ -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\ResourceBundle\Reader;
use Symfony\Component\Intl\ResourceBundle\Util\RingBuffer;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class BufferedBundleReader 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);
}
}

View file

@ -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);
}

View file

@ -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';
}
}

View file

@ -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, $fallback = true)
{
$data = $this->reader->read($path, $locale);
$entry = RecursiveArrayAccess::get($data, $indices);
$multivalued = is_array($entry) || $entry instanceof \Traversable;
if (!($fallback && (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);
}
}

View file

@ -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\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 $fallback 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
* (i.e. array or \ArrayAccess) or cannot be found
* in the requested locale.
*
* @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, $fallback = true);
}

View file

@ -0,0 +1,52 @@
<?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($country, $locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
return $this->readEntry($locale, array('Countries', $country));
}
/**
* {@inheritdoc}
*/
public function getCountryNames($locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
if (null === ($countries = $this->readEntry($locale, array('Countries')))) {
return array();
}
if ($countries instanceof \Traversable) {
$countries = iterator_to_array($countries);
}
return $countries;
}
}

View file

@ -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\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 $country A country code (e.g. "US").
* @param string $locale Optional. The locale to return the name in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The name of the country or NULL if not found.
*/
public function getCountryName($country, $locale = null);
/**
* Returns the names of all known countries.
*
* @param string $locale Optional. The locale to return the names in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string[] A list of country names indexed by country codes.
*/
public function getCountryNames($locale = null);
}

View file

@ -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();
}

View file

@ -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);
}
}
}

View file

@ -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\BundleCompilerInterface;
/**
* 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 BundleCompilerInterface
*/
private $compiler;
/**
* @var string
*/
private $icuVersion;
public function __construct($sourceDir, $binaryDir, Filesystem $filesystem, BundleCompilerInterface $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;
}
}

View file

@ -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\BundleCompilerInterface 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();
}

View file

@ -0,0 +1,94 @@
<?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;
use Symfony\Component\Intl\Util\IcuVersion;
/**
* 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 (IcuVersion::compare($context->getIcuVersion(), '4.2', '<=', 1)) {
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($code, 'en'),
CurrencyBundle::INDEX_FRACTION_DIGITS => $currencyBundle->getFractionDigits($code),
CurrencyBundle::INDEX_ROUNDING_INCREMENT => $currencyBundle->getRoundingIncrement($code),
);
}
return array(
'Currencies' => $currencies,
);
}
/**
* {@inheritdoc}
*/
public function afterCreateStub(StubbingContextInterface $context)
{
}
}

View 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\Transformer\Rule;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
use Symfony\Component\Intl\Util\IcuVersion;
/**
* 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 (IcuVersion::compare($context->getIcuVersion(), '4.2', '<=', 1)) {
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)
{
}
}

View file

@ -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($lang, null, $displayLocale))) {
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($script, $lang, $displayLocale))) {
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($region, $displayLocale))) {
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;
}
}

View file

@ -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;
use Symfony\Component\Intl\Util\IcuVersion;
/**
* 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 (IcuVersion::compare($context->getIcuVersion(), '4.2', '<=', 1)) {
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)
{
}
}

View file

@ -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);
}

View 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.
*/
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;
}
}

View file

@ -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();
}

View file

@ -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();
}
}

View file

@ -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() {}
}

View file

@ -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]);
}
}
}

View file

@ -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);
}

View file

@ -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}
*/
public 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);
}
}

View file

@ -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));
}
}