composer update
This commit is contained in:
12
vendor/symfony/translation/CHANGELOG.md
vendored
12
vendor/symfony/translation/CHANGELOG.md
vendored
@@ -1,6 +1,18 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* Started using ICU parent locales as fallback locales.
|
||||
* allow using the ICU message format using domains with the "+intl-icu" suffix
|
||||
* deprecated `Translator::transChoice()` in favor of using `Translator::trans()` with a `%count%` parameter
|
||||
* deprecated `TranslatorInterface` in favor of `Symfony\Contracts\Translation\TranslatorInterface`
|
||||
* deprecated `MessageSelector`, `Interval` and `PluralizationRules`; use `IdentityTranslator` instead
|
||||
* Added `IntlFormatter` and `IntlFormatterInterface`
|
||||
* added support for multiple files and directories in `XliffLintCommand`
|
||||
* Marked `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` as internal
|
||||
|
||||
4.1.0
|
||||
-----
|
||||
|
||||
|
@@ -31,7 +31,7 @@ abstract class AbstractOperation implements OperationInterface
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* @var null|array The domains affected by this operation
|
||||
* @var array|null The domains affected by this operation
|
||||
*/
|
||||
private $domains;
|
||||
|
||||
@@ -39,21 +39,20 @@ abstract class AbstractOperation implements OperationInterface
|
||||
* This array stores 'all', 'new' and 'obsolete' messages for all valid domains.
|
||||
*
|
||||
* The data structure of this array is as follows:
|
||||
* ```php
|
||||
* array(
|
||||
* 'domain 1' => array(
|
||||
* 'all' => array(...),
|
||||
* 'new' => array(...),
|
||||
* 'obsolete' => array(...)
|
||||
* ),
|
||||
* 'domain 2' => array(
|
||||
* 'all' => array(...),
|
||||
* 'new' => array(...),
|
||||
* 'obsolete' => array(...)
|
||||
* ),
|
||||
* ...
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* array(
|
||||
* 'domain 1' => array(
|
||||
* 'all' => array(...),
|
||||
* 'new' => array(...),
|
||||
* 'obsolete' => array(...)
|
||||
* ),
|
||||
* 'domain 2' => array(
|
||||
* 'all' => array(...),
|
||||
* 'new' => array(...),
|
||||
* 'obsolete' => array(...)
|
||||
* ),
|
||||
* ...
|
||||
* )
|
||||
*
|
||||
* @var array The array that stores 'all', 'new' and 'obsolete' messages
|
||||
*/
|
||||
|
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Translation\Catalogue;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
|
||||
/**
|
||||
* Merge operation between two catalogues as follows:
|
||||
* all = source ∪ target = {x: x ∈ source ∨ x ∈ target}
|
||||
@@ -32,10 +34,11 @@ class MergeOperation extends AbstractOperation
|
||||
'new' => array(),
|
||||
'obsolete' => array(),
|
||||
);
|
||||
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
|
||||
|
||||
foreach ($this->source->all($domain) as $id => $message) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$this->result->add(array($id => $message), $domain);
|
||||
$this->result->add(array($id => $message), $this->source->defines($id, $intlDomain) ? $intlDomain : $domain);
|
||||
if (null !== $keyMetadata = $this->source->getMetadata($id, $domain)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $domain);
|
||||
}
|
||||
@@ -45,7 +48,7 @@ class MergeOperation extends AbstractOperation
|
||||
if (!$this->source->has($id, $domain)) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$this->messages[$domain]['new'][$id] = $message;
|
||||
$this->result->add(array($id => $message), $domain);
|
||||
$this->result->add(array($id => $message), $this->target->defines($id, $intlDomain) ? $intlDomain : $domain);
|
||||
if (null !== $keyMetadata = $this->target->getMetadata($id, $domain)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $domain);
|
||||
}
|
||||
|
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Translation\Catalogue;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
|
||||
/**
|
||||
* Target operation between two catalogues:
|
||||
* intersection = source ∩ target = {x: x ∈ source ∧ x ∈ target}
|
||||
@@ -33,6 +35,7 @@ class TargetOperation extends AbstractOperation
|
||||
'new' => array(),
|
||||
'obsolete' => array(),
|
||||
);
|
||||
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
|
||||
|
||||
// For 'all' messages, the code can't be simplified as ``$this->messages[$domain]['all'] = $target->all($domain);``,
|
||||
// because doing so will drop messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
|
||||
@@ -46,7 +49,7 @@ class TargetOperation extends AbstractOperation
|
||||
foreach ($this->source->all($domain) as $id => $message) {
|
||||
if ($this->target->has($id, $domain)) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$this->result->add(array($id => $message), $domain);
|
||||
$this->result->add(array($id => $message), $this->target->defines($id, $intlDomain) ? $intlDomain : $domain);
|
||||
if (null !== $keyMetadata = $this->source->getMetadata($id, $domain)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $domain);
|
||||
}
|
||||
@@ -59,7 +62,7 @@ class TargetOperation extends AbstractOperation
|
||||
if (!$this->source->has($id, $domain)) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$this->messages[$domain]['new'][$id] = $message;
|
||||
$this->result->add(array($id => $message), $domain);
|
||||
$this->result->add(array($id => $message), $this->target->defines($id, $intlDomain) ? $intlDomain : $domain);
|
||||
if (null !== $keyMetadata = $this->target->getMetadata($id, $domain)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $domain);
|
||||
}
|
||||
|
@@ -13,10 +13,12 @@ namespace Symfony\Component\Translation\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Translation\Util\XliffUtils;
|
||||
|
||||
/**
|
||||
* Validates XLIFF files syntax and outputs encountered errors.
|
||||
@@ -33,13 +35,15 @@ class XliffLintCommand extends Command
|
||||
private $displayCorrectFiles;
|
||||
private $directoryIteratorProvider;
|
||||
private $isReadableProvider;
|
||||
private $requireStrictFileNames;
|
||||
|
||||
public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null)
|
||||
public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null, bool $requireStrictFileNames = true)
|
||||
{
|
||||
parent::__construct($name);
|
||||
|
||||
$this->directoryIteratorProvider = $directoryIteratorProvider;
|
||||
$this->isReadableProvider = $isReadableProvider;
|
||||
$this->requireStrictFileNames = $requireStrictFileNames;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +53,7 @@ class XliffLintCommand extends Command
|
||||
{
|
||||
$this
|
||||
->setDescription('Lints a XLIFF file and outputs encountered errors')
|
||||
->addArgument('filename', null, 'A file or a directory or STDIN')
|
||||
->addArgument('filename', InputArgument::IS_ARRAY, 'A file or a directory or STDIN')
|
||||
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
|
||||
->setHelp(<<<EOF
|
||||
The <info>%command.name%</info> command lints a XLIFF file and outputs to STDOUT
|
||||
@@ -76,11 +80,11 @@ EOF
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$filename = $input->getArgument('filename');
|
||||
$filenames = (array) $input->getArgument('filename');
|
||||
$this->format = $input->getOption('format');
|
||||
$this->displayCorrectFiles = $output->isVerbose();
|
||||
|
||||
if (!$filename) {
|
||||
if (0 === \count($filenames)) {
|
||||
if (!$stdin = $this->getStdin()) {
|
||||
throw new RuntimeException('Please provide a filename or pipe file content to STDIN.');
|
||||
}
|
||||
@@ -88,13 +92,15 @@ EOF
|
||||
return $this->display($io, array($this->validate($stdin)));
|
||||
}
|
||||
|
||||
if (!$this->isReadable($filename)) {
|
||||
throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
|
||||
}
|
||||
|
||||
$filesInfo = array();
|
||||
foreach ($this->getFiles($filename) as $file) {
|
||||
$filesInfo[] = $this->validate(file_get_contents($file), $file);
|
||||
foreach ($filenames as $filename) {
|
||||
if (!$this->isReadable($filename)) {
|
||||
throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
|
||||
}
|
||||
|
||||
foreach ($this->getFiles($filename) as $file) {
|
||||
$filesInfo[] = $this->validate(file_get_contents($file), $file);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->display($io, $filesInfo);
|
||||
@@ -115,30 +121,28 @@ EOF
|
||||
$document->loadXML($content);
|
||||
|
||||
if (null !== $targetLanguage = $this->getTargetLanguageFromFile($document)) {
|
||||
$expectedFileExtension = sprintf('%s.xlf', str_replace('-', '_', $targetLanguage));
|
||||
$realFileExtension = explode('.', basename($file), 2)[1] ?? '';
|
||||
$normalizedLocale = preg_quote(str_replace('-', '_', $targetLanguage), '/');
|
||||
// strict file names require translation files to be named '____.locale.xlf'
|
||||
// otherwise, both '____.locale.xlf' and 'locale.____.xlf' are allowed
|
||||
$expectedFilenamePattern = $this->requireStrictFileNames ? sprintf('/^.*\.%s\.xlf/', $normalizedLocale) : sprintf('/^(.*\.%s\.xlf|%s\..*\.xlf)/', $normalizedLocale, $normalizedLocale);
|
||||
|
||||
if ($expectedFileExtension !== $realFileExtension) {
|
||||
if (0 === preg_match($expectedFilenamePattern, basename($file))) {
|
||||
$errors[] = array(
|
||||
'line' => -1,
|
||||
'column' => -1,
|
||||
'message' => sprintf('There is a mismatch between the file extension ("%s") and the "%s" value used in the "target-language" attribute of the file.', $realFileExtension, $targetLanguage),
|
||||
'message' => sprintf('There is a mismatch between the language included in the file name ("%s") and the "%s" value used in the "target-language" attribute of the file.', basename($file), $targetLanguage),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$document->schemaValidate(__DIR__.'/../Resources/schemas/xliff-core-1.2-strict.xsd');
|
||||
foreach (libxml_get_errors() as $xmlError) {
|
||||
foreach (XliffUtils::validateSchema($document) as $xmlError) {
|
||||
$errors[] = array(
|
||||
'line' => $xmlError->line,
|
||||
'column' => $xmlError->column,
|
||||
'message' => trim($xmlError->message),
|
||||
'line' => $xmlError['line'],
|
||||
'column' => $xmlError['column'],
|
||||
'message' => $xmlError['message'],
|
||||
);
|
||||
}
|
||||
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors(false);
|
||||
|
||||
return array('file' => $file, 'valid' => 0 === \count($errors), 'messages' => $errors);
|
||||
}
|
||||
|
||||
|
3
vendor/symfony/translation/DataCollector/TranslationDataCollector.php
vendored
Normal file → Executable file
3
vendor/symfony/translation/DataCollector/TranslationDataCollector.php
vendored
Normal file → Executable file
@@ -97,6 +97,9 @@ class TranslationDataCollector extends DataCollector implements LateDataCollecto
|
||||
return !empty($this->data['locale']) ? $this->data['locale'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal since Symfony 4.2
|
||||
*/
|
||||
public function getFallbackLocales()
|
||||
{
|
||||
return (isset($this->data['fallback_locales']) && \count($this->data['fallback_locales']) > 0) ? $this->data['fallback_locales'] : array();
|
||||
|
@@ -12,11 +12,13 @@
|
||||
namespace Symfony\Component\Translation;
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*/
|
||||
class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInterface
|
||||
class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorInterface, TranslatorBagInterface
|
||||
{
|
||||
const MESSAGE_DEFINED = 0;
|
||||
const MESSAGE_MISSING = 1;
|
||||
@@ -32,8 +34,11 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter
|
||||
/**
|
||||
* @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
|
||||
*/
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
public function __construct($translator)
|
||||
{
|
||||
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||
}
|
||||
if (!$translator instanceof TranslatorBagInterface) {
|
||||
throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface and TranslatorBagInterface.', \get_class($translator)));
|
||||
}
|
||||
@@ -54,11 +59,18 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
|
||||
*/
|
||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
||||
{
|
||||
if ($this->translator instanceof TranslatorInterface) {
|
||||
$trans = $this->translator->trans($id, array('%count%' => $number) + $parameters, $domain, $locale);
|
||||
}
|
||||
|
||||
$trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
|
||||
$this->collectMessage($locale, $domain, $id, $trans, $parameters, $number);
|
||||
|
||||
$this->collectMessage($locale, $domain, $id, $trans, array('%count%' => $number) + $parameters);
|
||||
|
||||
return $trans;
|
||||
}
|
||||
@@ -90,7 +102,7 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter
|
||||
/**
|
||||
* Gets the fallback locales.
|
||||
*
|
||||
* @return array $locales The fallback locales
|
||||
* @return array The fallback locales
|
||||
*/
|
||||
public function getFallbackLocales()
|
||||
{
|
||||
@@ -106,7 +118,7 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
return \call_user_func_array(array($this->translator, $method), $args);
|
||||
return $this->translator->{$method}(...$args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,9 +135,8 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter
|
||||
* @param string $id
|
||||
* @param string $translation
|
||||
* @param array|null $parameters
|
||||
* @param int|null $number
|
||||
*/
|
||||
private function collectMessage($locale, $domain, $id, $translation, $parameters = array(), $number = null)
|
||||
private function collectMessage($locale, $domain, $id, $translation, $parameters = array())
|
||||
{
|
||||
if (null === $domain) {
|
||||
$domain = 'messages';
|
||||
@@ -158,8 +169,8 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter
|
||||
'id' => $id,
|
||||
'translation' => $translation,
|
||||
'parameters' => $parameters,
|
||||
'transChoiceNumber' => $number,
|
||||
'state' => $state,
|
||||
'transChoiceNumber' => isset($parameters['%count%']) && is_numeric($parameters['%count%']) ? $parameters['%count%'] : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ class CsvFileDumper extends FileDumper
|
||||
*/
|
||||
public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
|
||||
{
|
||||
$handle = fopen('php://memory', 'rb+');
|
||||
$handle = fopen('php://memory', 'r+b');
|
||||
|
||||
foreach ($messages->all($domain) as $source => $target) {
|
||||
fputcsv($handle, array($source, $target), $this->delimiter, $this->enclosure);
|
||||
|
23
vendor/symfony/translation/Dumper/FileDumper.php
vendored
23
vendor/symfony/translation/Dumper/FileDumper.php
vendored
@@ -45,7 +45,7 @@ abstract class FileDumper implements DumperInterface
|
||||
/**
|
||||
* Sets backup flag.
|
||||
*
|
||||
* @param bool
|
||||
* @param bool $backup
|
||||
*
|
||||
* @deprecated since Symfony 4.1
|
||||
*/
|
||||
@@ -76,7 +76,26 @@ abstract class FileDumper implements DumperInterface
|
||||
throw new RuntimeException(sprintf('Unable to create directory "%s".', $directory));
|
||||
}
|
||||
}
|
||||
// save file
|
||||
|
||||
$intlDomain = $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX;
|
||||
$intlMessages = $messages->all($intlDomain);
|
||||
|
||||
if ($intlMessages) {
|
||||
$intlPath = $options['path'].'/'.$this->getRelativePath($intlDomain, $messages->getLocale());
|
||||
file_put_contents($intlPath, $this->formatCatalogue($messages, $intlDomain, $options));
|
||||
|
||||
$messages->replace(array(), $intlDomain);
|
||||
|
||||
try {
|
||||
if ($messages->all($domain)) {
|
||||
file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
|
||||
}
|
||||
continue;
|
||||
} finally {
|
||||
$messages->replace($intlMessages, $intlDomain);
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
|
||||
}
|
||||
}
|
||||
|
@@ -25,11 +25,7 @@ class JsonFileDumper extends FileDumper
|
||||
*/
|
||||
public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
|
||||
{
|
||||
if (isset($options['json_encoding'])) {
|
||||
$flags = $options['json_encoding'];
|
||||
} else {
|
||||
$flags = JSON_PRETTY_PRINT;
|
||||
}
|
||||
$flags = $options['json_encoding'] ?? JSON_PRETTY_PRINT;
|
||||
|
||||
return json_encode($messages->all($domain), $flags);
|
||||
}
|
||||
|
@@ -57,7 +57,7 @@ class MoFileDumper extends FileDumper
|
||||
.$this->writeLong($offset[2] + $sourcesStart + $sourcesSize);
|
||||
}
|
||||
|
||||
$output = implode(array_map(array($this, 'writeLong'), $header))
|
||||
$output = implode('', array_map(array($this, 'writeLong'), $header))
|
||||
.$sourceOffsets
|
||||
.$targetOffsets
|
||||
.$sources
|
||||
|
@@ -16,6 +16,6 @@ namespace Symfony\Component\Translation\Exception;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface ExceptionInterface
|
||||
interface ExceptionInterface extends \Throwable
|
||||
{
|
||||
}
|
||||
|
@@ -89,7 +89,7 @@ class PhpStringTokenParser
|
||||
* Parses escape sequences in strings (all string types apart from single quoted).
|
||||
*
|
||||
* @param string $str String without quotes
|
||||
* @param null|string $quote Quote type
|
||||
* @param string|null $quote Quote type
|
||||
*
|
||||
* @return string String with escape sequences parsed
|
||||
*/
|
||||
|
@@ -13,6 +13,8 @@ namespace Symfony\Component\Translation\Formatter;
|
||||
|
||||
/**
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use MessageFormatterInterface::format() with a %count% parameter instead
|
||||
*/
|
||||
interface ChoiceMessageFormatterInterface
|
||||
{
|
||||
|
55
vendor/symfony/translation/Formatter/IntlFormatter.php
vendored
Normal file
55
vendor/symfony/translation/Formatter/IntlFormatter.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?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\Translation\Formatter;
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\Exception\LogicException;
|
||||
|
||||
/**
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*/
|
||||
class IntlFormatter implements IntlFormatterInterface
|
||||
{
|
||||
private $hasMessageFormatter;
|
||||
private $cache = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function formatIntl(string $message, string $locale, array $parameters = array()): string
|
||||
{
|
||||
if (!$formatter = $this->cache[$locale][$message] ?? null) {
|
||||
if (!($this->hasMessageFormatter ?? $this->hasMessageFormatter = class_exists(\MessageFormatter::class))) {
|
||||
throw new LogicException('Cannot parse message translation: please install the "intl" PHP extension or the "symfony/polyfill-intl-messageformatter" package.');
|
||||
}
|
||||
try {
|
||||
$this->cache[$locale][$message] = $formatter = new \MessageFormatter($locale, $message);
|
||||
} catch (\IntlException $e) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid message format (error #%d): %s.', intl_get_error_code(), intl_get_error_message()), 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($parameters as $key => $value) {
|
||||
if (\in_array($key[0] ?? null, array('%', '{'), true)) {
|
||||
unset($parameters[$key]);
|
||||
$parameters[trim($key, '%{ }')] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (false === $message = $formatter->format($parameters)) {
|
||||
throw new InvalidArgumentException(sprintf('Unable to format message (error #%s): %s.', $formatter->getErrorCode(), $formatter->getErrorMessage()));
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
27
vendor/symfony/translation/Formatter/IntlFormatterInterface.php
vendored
Normal file
27
vendor/symfony/translation/Formatter/IntlFormatterInterface.php
vendored
Normal 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\Translation\Formatter;
|
||||
|
||||
/**
|
||||
* Formats ICU message patterns.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
interface IntlFormatterInterface
|
||||
{
|
||||
/**
|
||||
* Formats a localized message using rules defined by ICU MessageFormat.
|
||||
*
|
||||
* @see http://icu-project.org/apiref/icu4c/classMessageFormat.html#details
|
||||
*/
|
||||
public function formatIntl(string $message, string $locale, array $parameters = array()): string;
|
||||
}
|
@@ -11,21 +11,32 @@
|
||||
|
||||
namespace Symfony\Component\Translation\Formatter;
|
||||
|
||||
use Symfony\Component\Translation\IdentityTranslator;
|
||||
use Symfony\Component\Translation\MessageSelector;
|
||||
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*/
|
||||
class MessageFormatter implements MessageFormatterInterface, ChoiceMessageFormatterInterface
|
||||
class MessageFormatter implements MessageFormatterInterface, IntlFormatterInterface, ChoiceMessageFormatterInterface
|
||||
{
|
||||
private $selector;
|
||||
private $translator;
|
||||
private $intlFormatter;
|
||||
|
||||
/**
|
||||
* @param MessageSelector|null $selector The message selector for pluralization
|
||||
* @param TranslatorInterface|null $translator An identity translator to use as selector for pluralization
|
||||
*/
|
||||
public function __construct(MessageSelector $selector = null)
|
||||
public function __construct($translator = null, IntlFormatterInterface $intlFormatter = null)
|
||||
{
|
||||
$this->selector = $selector ?: new MessageSelector();
|
||||
if ($translator instanceof MessageSelector) {
|
||||
$translator = new IdentityTranslator($translator);
|
||||
} elseif (null !== $translator && !$translator instanceof TranslatorInterface && !$translator instanceof LegacyTranslatorInterface) {
|
||||
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||
}
|
||||
|
||||
$this->translator = $translator ?? new IdentityTranslator();
|
||||
$this->intlFormatter = $intlFormatter ?? new IntlFormatter();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,16 +44,36 @@ class MessageFormatter implements MessageFormatterInterface, ChoiceMessageFormat
|
||||
*/
|
||||
public function format($message, $locale, array $parameters = array())
|
||||
{
|
||||
if ($this->translator instanceof TranslatorInterface) {
|
||||
return $this->translator->trans($message, $parameters, null, $locale);
|
||||
}
|
||||
|
||||
return strtr($message, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function formatIntl(string $message, string $locale, array $parameters = array()): string
|
||||
{
|
||||
return $this->intlFormatter->formatIntl($message, $locale, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use format() with a %count% parameter instead
|
||||
*/
|
||||
public function choiceFormat($message, $number, $locale, array $parameters = array())
|
||||
{
|
||||
$parameters = array_merge(array('%count%' => $number), $parameters);
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the format() one instead with a %count% parameter.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return $this->format($this->selector->choose($message, (int) $number, $locale), $locale, $parameters);
|
||||
$parameters = array('%count%' => $number) + $parameters;
|
||||
|
||||
if ($this->translator instanceof TranslatorInterface) {
|
||||
return $this->format($message, $locale, $parameters);
|
||||
}
|
||||
|
||||
return $this->format($this->translator->transChoice($message, $number, array(), null, $locale), $locale, $parameters);
|
||||
}
|
||||
}
|
||||
|
@@ -11,53 +11,51 @@
|
||||
|
||||
namespace Symfony\Component\Translation;
|
||||
|
||||
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorTrait;
|
||||
|
||||
/**
|
||||
* IdentityTranslator does not translate anything.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class IdentityTranslator implements TranslatorInterface
|
||||
class IdentityTranslator implements LegacyTranslatorInterface, TranslatorInterface
|
||||
{
|
||||
use TranslatorTrait;
|
||||
|
||||
private $selector;
|
||||
private $locale;
|
||||
|
||||
/**
|
||||
* @param MessageSelector|null $selector The message selector for pluralization
|
||||
*/
|
||||
public function __construct(MessageSelector $selector = null)
|
||||
{
|
||||
$this->selector = $selector ?: new MessageSelector();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setLocale($locale)
|
||||
{
|
||||
$this->locale = $locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLocale()
|
||||
{
|
||||
return $this->locale ?: \Locale::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function trans($id, array $parameters = array(), $domain = null, $locale = null)
|
||||
{
|
||||
return strtr((string) $id, $parameters);
|
||||
$this->selector = $selector;
|
||||
|
||||
if (__CLASS__ !== \get_class($this)) {
|
||||
@trigger_error(sprintf('Calling "%s()" is deprecated since Symfony 4.2.'), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
|
||||
*/
|
||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
||||
{
|
||||
return strtr($this->selector->choose((string) $id, (int) $number, $locale ?: $this->getLocale()), $parameters);
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%count%" parameter.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
if ($this->selector) {
|
||||
return strtr($this->selector->choose((string) $id, $number, $locale ?: $this->getLocale()), $parameters);
|
||||
}
|
||||
|
||||
return $this->trans($id, array('%count%' => $number) + $parameters, $domain, $locale);
|
||||
}
|
||||
|
||||
private function getPluralizationRule(int $number, string $locale): int
|
||||
{
|
||||
return PluralizationRules::get($number, $locale, false);
|
||||
}
|
||||
}
|
||||
|
3
vendor/symfony/translation/Interval.php
vendored
3
vendor/symfony/translation/Interval.php
vendored
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Translation;
|
||||
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2, use IdentityTranslator instead.', Interval::class), E_USER_DEPRECATED);
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
@@ -32,6 +34,7 @@ use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @see http://en.wikipedia.org/wiki/Interval_%28mathematics%29#The_ISO_notation
|
||||
* @deprecated since Symfony 4.2, use IdentityTranslator instead
|
||||
*/
|
||||
class Interval
|
||||
{
|
||||
|
@@ -13,10 +13,10 @@ namespace Symfony\Component\Translation\Loader;
|
||||
|
||||
use Symfony\Component\Config\Resource\FileResource;
|
||||
use Symfony\Component\Config\Util\XmlUtils;
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\Exception\InvalidResourceException;
|
||||
use Symfony\Component\Translation\Exception\NotFoundResourceException;
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
use Symfony\Component\Translation\Util\XliffUtils;
|
||||
|
||||
/**
|
||||
* XliffFileLoader loads translations from XLIFF files.
|
||||
@@ -56,8 +56,10 @@ class XliffFileLoader implements LoaderInterface
|
||||
throw new InvalidResourceException(sprintf('Unable to load "%s": %s', $resource, $e->getMessage()), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
$xliffVersion = $this->getVersionNumber($dom);
|
||||
$this->validateSchema($xliffVersion, $dom, $this->getSchema($xliffVersion));
|
||||
$xliffVersion = XliffUtils::getVersionNumber($dom);
|
||||
if ($errors = XliffUtils::validateSchema($dom)) {
|
||||
throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: %s', $xliffVersion, XliffUtils::getErrorsAsString($errors)));
|
||||
}
|
||||
|
||||
if ('1.2' === $xliffVersion) {
|
||||
$this->extractXliff1($dom, $catalogue, $domain);
|
||||
@@ -91,7 +93,7 @@ class XliffFileLoader implements LoaderInterface
|
||||
$source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source;
|
||||
// If the xlf file has another encoding specified, try to convert it because
|
||||
// simple_xml will always return utf-8 encoded values
|
||||
$target = $this->utf8ToCharset((string) (isset($translation->target) ? $translation->target : $source), $encoding);
|
||||
$target = $this->utf8ToCharset((string) (isset($translation->target) ? $translation->target : $translation->source), $encoding);
|
||||
|
||||
$catalogue->set((string) $source, $target, $domain);
|
||||
|
||||
@@ -169,123 +171,6 @@ class XliffFileLoader implements LoaderInterface
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and parses the given file into a DOMDocument.
|
||||
*
|
||||
* @throws InvalidResourceException
|
||||
*/
|
||||
private function validateSchema(string $file, \DOMDocument $dom, string $schema)
|
||||
{
|
||||
$internalErrors = libxml_use_internal_errors(true);
|
||||
|
||||
$disableEntities = libxml_disable_entity_loader(false);
|
||||
|
||||
if (!@$dom->schemaValidateSource($schema)) {
|
||||
libxml_disable_entity_loader($disableEntities);
|
||||
|
||||
throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: %s', $file, implode("\n", $this->getXmlErrors($internalErrors))));
|
||||
}
|
||||
|
||||
libxml_disable_entity_loader($disableEntities);
|
||||
|
||||
$dom->normalizeDocument();
|
||||
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors($internalErrors);
|
||||
}
|
||||
|
||||
private function getSchema($xliffVersion)
|
||||
{
|
||||
if ('1.2' === $xliffVersion) {
|
||||
$schemaSource = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-1.2-strict.xsd');
|
||||
$xmlUri = 'http://www.w3.org/2001/xml.xsd';
|
||||
} elseif ('2.0' === $xliffVersion) {
|
||||
$schemaSource = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-2.0.xsd');
|
||||
$xmlUri = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd';
|
||||
} else {
|
||||
throw new InvalidArgumentException(sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion));
|
||||
}
|
||||
|
||||
return $this->fixXmlLocation($schemaSource, $xmlUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internally changes the URI of a dependent xsd to be loaded locally.
|
||||
*/
|
||||
private function fixXmlLocation(string $schemaSource, string $xmlUri): string
|
||||
{
|
||||
$newPath = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd';
|
||||
$parts = explode('/', $newPath);
|
||||
$locationstart = 'file:///';
|
||||
if (0 === stripos($newPath, 'phar://')) {
|
||||
$tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
|
||||
if ($tmpfile) {
|
||||
copy($newPath, $tmpfile);
|
||||
$parts = explode('/', str_replace('\\', '/', $tmpfile));
|
||||
} else {
|
||||
array_shift($parts);
|
||||
$locationstart = 'phar:///';
|
||||
}
|
||||
}
|
||||
|
||||
$drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
|
||||
$newPath = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts));
|
||||
|
||||
return str_replace($xmlUri, $newPath, $schemaSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the XML errors of the internal XML parser.
|
||||
*/
|
||||
private function getXmlErrors(bool $internalErrors): array
|
||||
{
|
||||
$errors = array();
|
||||
foreach (libxml_get_errors() as $error) {
|
||||
$errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
|
||||
LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
|
||||
$error->code,
|
||||
trim($error->message),
|
||||
$error->file ?: 'n/a',
|
||||
$error->line,
|
||||
$error->column
|
||||
);
|
||||
}
|
||||
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors($internalErrors);
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets xliff file version based on the root "version" attribute.
|
||||
* Defaults to 1.2 for backwards compatibility.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function getVersionNumber(\DOMDocument $dom): string
|
||||
{
|
||||
/** @var \DOMNode $xliff */
|
||||
foreach ($dom->getElementsByTagName('xliff') as $xliff) {
|
||||
$version = $xliff->attributes->getNamedItem('version');
|
||||
if ($version) {
|
||||
return $version->nodeValue;
|
||||
}
|
||||
|
||||
$namespace = $xliff->attributes->getNamedItem('xmlns');
|
||||
if ($namespace) {
|
||||
if (0 !== substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34)) {
|
||||
throw new InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s"', $namespace));
|
||||
}
|
||||
|
||||
return substr($namespace, 34);
|
||||
}
|
||||
}
|
||||
|
||||
// Falls back to v1.2
|
||||
return '1.2';
|
||||
}
|
||||
|
||||
private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, string $encoding = null): array
|
||||
{
|
||||
$notes = array();
|
||||
|
File diff suppressed because it is too large
Load Diff
24
vendor/symfony/translation/LoggingTranslator.php
vendored
24
vendor/symfony/translation/LoggingTranslator.php
vendored
@@ -13,11 +13,13 @@ namespace Symfony\Component\Translation;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*/
|
||||
class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface
|
||||
class LoggingTranslator implements TranslatorInterface, LegacyTranslatorInterface, TranslatorBagInterface
|
||||
{
|
||||
/**
|
||||
* @var TranslatorInterface|TranslatorBagInterface
|
||||
@@ -30,8 +32,11 @@ class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface
|
||||
* @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(TranslatorInterface $translator, LoggerInterface $logger)
|
||||
public function __construct($translator, LoggerInterface $logger)
|
||||
{
|
||||
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||
}
|
||||
if (!$translator instanceof TranslatorBagInterface) {
|
||||
throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface and TranslatorBagInterface.', \get_class($translator)));
|
||||
}
|
||||
@@ -53,10 +58,19 @@ class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
|
||||
*/
|
||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
||||
{
|
||||
$trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%count%" parameter.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
if ($this->translator instanceof TranslatorInterface) {
|
||||
$trans = $this->translator->trans($id, array('%count%' => $number) + $parameters, $domain, $locale);
|
||||
} else {
|
||||
$trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
|
||||
}
|
||||
|
||||
$this->log($id, $domain, $locale);
|
||||
|
||||
return $trans;
|
||||
@@ -89,7 +103,7 @@ class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface
|
||||
/**
|
||||
* Gets the fallback locales.
|
||||
*
|
||||
* @return array $locales The fallback locales
|
||||
* @return array The fallback locales
|
||||
*/
|
||||
public function getFallbackLocales()
|
||||
{
|
||||
@@ -105,7 +119,7 @@ class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
return \call_user_func_array(array($this->translator, $method), $args);
|
||||
return $this->translator->{$method}(...$args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
44
vendor/symfony/translation/MessageCatalogue.php
vendored
44
vendor/symfony/translation/MessageCatalogue.php
vendored
@@ -49,7 +49,17 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
|
||||
*/
|
||||
public function getDomains()
|
||||
{
|
||||
return array_keys($this->messages);
|
||||
$domains = array();
|
||||
$suffixLength = \strlen(self::INTL_DOMAIN_SUFFIX);
|
||||
|
||||
foreach ($this->messages as $domain => $messages) {
|
||||
if (\strlen($domain) > $suffixLength && false !== $i = strpos($domain, self::INTL_DOMAIN_SUFFIX, -$suffixLength)) {
|
||||
$domain = substr($domain, 0, $i);
|
||||
}
|
||||
$domains[$domain] = $domain;
|
||||
}
|
||||
|
||||
return array_values($domains);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,11 +67,23 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
|
||||
*/
|
||||
public function all($domain = null)
|
||||
{
|
||||
if (null === $domain) {
|
||||
return $this->messages;
|
||||
if (null !== $domain) {
|
||||
return ($this->messages[$domain.self::INTL_DOMAIN_SUFFIX] ?? array()) + ($this->messages[$domain] ?? array());
|
||||
}
|
||||
|
||||
return isset($this->messages[$domain]) ? $this->messages[$domain] : array();
|
||||
$allMessages = array();
|
||||
$suffixLength = \strlen(self::INTL_DOMAIN_SUFFIX);
|
||||
|
||||
foreach ($this->messages as $domain => $messages) {
|
||||
if (\strlen($domain) > $suffixLength && false !== $i = strpos($domain, self::INTL_DOMAIN_SUFFIX, -$suffixLength)) {
|
||||
$domain = substr($domain, 0, $i);
|
||||
$allMessages[$domain] = $messages + ($allMessages[$domain] ?? array());
|
||||
} else {
|
||||
$allMessages[$domain] = ($allMessages[$domain] ?? array()) + $messages;
|
||||
}
|
||||
}
|
||||
|
||||
return $allMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +99,7 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
|
||||
*/
|
||||
public function has($id, $domain = 'messages')
|
||||
{
|
||||
if (isset($this->messages[$domain][$id])) {
|
||||
if (isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -93,7 +115,7 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
|
||||
*/
|
||||
public function defines($id, $domain = 'messages')
|
||||
{
|
||||
return isset($this->messages[$domain][$id]);
|
||||
return isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,6 +123,10 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
|
||||
*/
|
||||
public function get($id, $domain = 'messages')
|
||||
{
|
||||
if (isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) {
|
||||
return $this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id];
|
||||
}
|
||||
|
||||
if (isset($this->messages[$domain][$id])) {
|
||||
return $this->messages[$domain][$id];
|
||||
}
|
||||
@@ -117,7 +143,7 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
|
||||
*/
|
||||
public function replace($messages, $domain = 'messages')
|
||||
{
|
||||
$this->messages[$domain] = array();
|
||||
unset($this->messages[$domain], $this->messages[$domain.self::INTL_DOMAIN_SUFFIX]);
|
||||
|
||||
$this->add($messages, $domain);
|
||||
}
|
||||
@@ -144,6 +170,10 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
|
||||
}
|
||||
|
||||
foreach ($catalogue->all() as $domain => $messages) {
|
||||
if ($intlMessages = $catalogue->all($domain.self::INTL_DOMAIN_SUFFIX)) {
|
||||
$this->add($intlMessages, $domain.self::INTL_DOMAIN_SUFFIX);
|
||||
$messages = array_diff_key($messages, $intlMessages);
|
||||
}
|
||||
$this->add($messages, $domain);
|
||||
}
|
||||
|
||||
|
@@ -20,6 +20,8 @@ use Symfony\Component\Config\Resource\ResourceInterface;
|
||||
*/
|
||||
interface MessageCatalogueInterface
|
||||
{
|
||||
const INTL_DOMAIN_SUFFIX = '+intl-icu';
|
||||
|
||||
/**
|
||||
* Gets the catalogue locale.
|
||||
*
|
||||
|
10
vendor/symfony/translation/MessageSelector.php
vendored
10
vendor/symfony/translation/MessageSelector.php
vendored
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Translation;
|
||||
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2, use IdentityTranslator instead.', MessageSelector::class), E_USER_DEPRECATED);
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
@@ -18,6 +20,8 @@ use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use IdentityTranslator instead.
|
||||
*/
|
||||
class MessageSelector
|
||||
{
|
||||
@@ -39,9 +43,9 @@ class MessageSelector
|
||||
* The two methods can also be mixed:
|
||||
* {0} There are no apples|one: There is one apple|more: There are %count% apples
|
||||
*
|
||||
* @param string $message The message being translated
|
||||
* @param int $number The number of items represented for the message
|
||||
* @param string $locale The locale to use for choosing
|
||||
* @param string $message The message being translated
|
||||
* @param int|float $number The number of items represented for the message
|
||||
* @param string $locale The locale to use for choosing
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
|
@@ -15,6 +15,8 @@ namespace Symfony\Component\Translation;
|
||||
* Returns the plural rules for a given locale.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use IdentityTranslator instead
|
||||
*/
|
||||
class PluralizationRules
|
||||
{
|
||||
@@ -28,8 +30,12 @@ class PluralizationRules
|
||||
*
|
||||
* @return int The plural position
|
||||
*/
|
||||
public static function get($number, $locale)
|
||||
public static function get($number, $locale/*, bool $triggerDeprecation = true*/)
|
||||
{
|
||||
if (3 > \func_num_args() || \func_get_arg(2)) {
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ('pt_BR' === $locale) {
|
||||
// temporary set a locale for brazilian
|
||||
$locale = 'xbr';
|
||||
@@ -196,6 +202,8 @@ class PluralizationRules
|
||||
*/
|
||||
public static function set(callable $rule, $locale)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED);
|
||||
|
||||
if ('pt_BR' === $locale) {
|
||||
// temporary set a locale for brazilian
|
||||
$locale = 'xbr';
|
||||
|
136
vendor/symfony/translation/Resources/data/parents.json
vendored
Normal file
136
vendor/symfony/translation/Resources/data/parents.json
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"az_Cyrl": "root",
|
||||
"bs_Cyrl": "root",
|
||||
"en_150": "en_001",
|
||||
"en_AG": "en_001",
|
||||
"en_AI": "en_001",
|
||||
"en_AT": "en_150",
|
||||
"en_AU": "en_001",
|
||||
"en_BB": "en_001",
|
||||
"en_BE": "en_001",
|
||||
"en_BM": "en_001",
|
||||
"en_BS": "en_001",
|
||||
"en_BW": "en_001",
|
||||
"en_BZ": "en_001",
|
||||
"en_CA": "en_001",
|
||||
"en_CC": "en_001",
|
||||
"en_CH": "en_150",
|
||||
"en_CK": "en_001",
|
||||
"en_CM": "en_001",
|
||||
"en_CX": "en_001",
|
||||
"en_CY": "en_001",
|
||||
"en_DE": "en_150",
|
||||
"en_DG": "en_001",
|
||||
"en_DK": "en_150",
|
||||
"en_DM": "en_001",
|
||||
"en_ER": "en_001",
|
||||
"en_FI": "en_150",
|
||||
"en_FJ": "en_001",
|
||||
"en_FK": "en_001",
|
||||
"en_FM": "en_001",
|
||||
"en_GB": "en_001",
|
||||
"en_GD": "en_001",
|
||||
"en_GG": "en_001",
|
||||
"en_GH": "en_001",
|
||||
"en_GI": "en_001",
|
||||
"en_GM": "en_001",
|
||||
"en_GY": "en_001",
|
||||
"en_HK": "en_001",
|
||||
"en_IE": "en_001",
|
||||
"en_IL": "en_001",
|
||||
"en_IM": "en_001",
|
||||
"en_IN": "en_001",
|
||||
"en_IO": "en_001",
|
||||
"en_JE": "en_001",
|
||||
"en_JM": "en_001",
|
||||
"en_KE": "en_001",
|
||||
"en_KI": "en_001",
|
||||
"en_KN": "en_001",
|
||||
"en_KY": "en_001",
|
||||
"en_LC": "en_001",
|
||||
"en_LR": "en_001",
|
||||
"en_LS": "en_001",
|
||||
"en_MG": "en_001",
|
||||
"en_MO": "en_001",
|
||||
"en_MS": "en_001",
|
||||
"en_MT": "en_001",
|
||||
"en_MU": "en_001",
|
||||
"en_MW": "en_001",
|
||||
"en_MY": "en_001",
|
||||
"en_NA": "en_001",
|
||||
"en_NF": "en_001",
|
||||
"en_NG": "en_001",
|
||||
"en_NL": "en_150",
|
||||
"en_NR": "en_001",
|
||||
"en_NU": "en_001",
|
||||
"en_NZ": "en_001",
|
||||
"en_PG": "en_001",
|
||||
"en_PH": "en_001",
|
||||
"en_PK": "en_001",
|
||||
"en_PN": "en_001",
|
||||
"en_PW": "en_001",
|
||||
"en_RW": "en_001",
|
||||
"en_SB": "en_001",
|
||||
"en_SC": "en_001",
|
||||
"en_SD": "en_001",
|
||||
"en_SE": "en_150",
|
||||
"en_SG": "en_001",
|
||||
"en_SH": "en_001",
|
||||
"en_SI": "en_150",
|
||||
"en_SL": "en_001",
|
||||
"en_SS": "en_001",
|
||||
"en_SX": "en_001",
|
||||
"en_SZ": "en_001",
|
||||
"en_TC": "en_001",
|
||||
"en_TK": "en_001",
|
||||
"en_TO": "en_001",
|
||||
"en_TT": "en_001",
|
||||
"en_TV": "en_001",
|
||||
"en_TZ": "en_001",
|
||||
"en_UG": "en_001",
|
||||
"en_VC": "en_001",
|
||||
"en_VG": "en_001",
|
||||
"en_VU": "en_001",
|
||||
"en_WS": "en_001",
|
||||
"en_ZA": "en_001",
|
||||
"en_ZM": "en_001",
|
||||
"en_ZW": "en_001",
|
||||
"es_AR": "es_419",
|
||||
"es_BO": "es_419",
|
||||
"es_BR": "es_419",
|
||||
"es_BZ": "es_419",
|
||||
"es_CL": "es_419",
|
||||
"es_CO": "es_419",
|
||||
"es_CR": "es_419",
|
||||
"es_CU": "es_419",
|
||||
"es_DO": "es_419",
|
||||
"es_EC": "es_419",
|
||||
"es_GT": "es_419",
|
||||
"es_HN": "es_419",
|
||||
"es_MX": "es_419",
|
||||
"es_NI": "es_419",
|
||||
"es_PA": "es_419",
|
||||
"es_PE": "es_419",
|
||||
"es_PR": "es_419",
|
||||
"es_PY": "es_419",
|
||||
"es_SV": "es_419",
|
||||
"es_US": "es_419",
|
||||
"es_UY": "es_419",
|
||||
"es_VE": "es_419",
|
||||
"pa_Arab": "root",
|
||||
"pt_AO": "pt_PT",
|
||||
"pt_CH": "pt_PT",
|
||||
"pt_CV": "pt_PT",
|
||||
"pt_GQ": "pt_PT",
|
||||
"pt_GW": "pt_PT",
|
||||
"pt_LU": "pt_PT",
|
||||
"pt_MO": "pt_PT",
|
||||
"pt_MZ": "pt_PT",
|
||||
"pt_ST": "pt_PT",
|
||||
"pt_TL": "pt_PT",
|
||||
"sr_Latn": "root",
|
||||
"uz_Arab": "root",
|
||||
"uz_Cyrl": "root",
|
||||
"zh_Hant": "root",
|
||||
"zh_Hant_MO": "zh_Hant_HK"
|
||||
}
|
@@ -30,7 +30,7 @@ Jan-10-2006
|
||||
-->
|
||||
<xsd:schema xmlns:xlf="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:xliff:document:1.2" xml:lang="en">
|
||||
<!-- Import for xml:lang and xml:space -->
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="../../Loader/schema/dic/xliff-core/xml.xsd"/>
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
|
||||
<!-- Attributes Lists -->
|
||||
<xsd:simpleType name="XTend">
|
||||
<xsd:restriction base="xsd:string">
|
||||
|
@@ -53,6 +53,20 @@ class MergeOperationTest extends AbstractOperationTest
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetResultFromIntlDomain()
|
||||
{
|
||||
$this->assertEquals(
|
||||
new MessageCatalogue('en', array(
|
||||
'messages' => array('a' => 'old_a', 'b' => 'old_b'),
|
||||
'messages+intl-icu' => array('d' => 'old_d', 'c' => 'new_c'),
|
||||
)),
|
||||
$this->createOperation(
|
||||
new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'), 'messages+intl-icu' => array('d' => 'old_d'))),
|
||||
new MessageCatalogue('en', array('messages+intl-icu' => array('a' => 'new_a', 'c' => 'new_c')))
|
||||
)->getResult()
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetResultWithMetadata()
|
||||
{
|
||||
$leftCatalogue = new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b')));
|
||||
|
@@ -53,6 +53,20 @@ class TargetOperationTest extends AbstractOperationTest
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetResultFromIntlDomain()
|
||||
{
|
||||
$this->assertEquals(
|
||||
new MessageCatalogue('en', array(
|
||||
'messages' => array('a' => 'old_a'),
|
||||
'messages+intl-icu' => array('c' => 'new_c'),
|
||||
)),
|
||||
$this->createOperation(
|
||||
new MessageCatalogue('en', array('messages' => array('a' => 'old_a'), 'messages+intl-icu' => array('b' => 'old_b'))),
|
||||
new MessageCatalogue('en', array('messages' => array('a' => 'new_a'), 'messages+intl-icu' => array('c' => 'new_c')))
|
||||
)->getResult()
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetResultWithMetadata()
|
||||
{
|
||||
$leftCatalogue = new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b')));
|
||||
|
@@ -40,6 +40,38 @@ class XliffLintCommandTest extends TestCase
|
||||
$this->assertContains('OK', trim($tester->getDisplay()));
|
||||
}
|
||||
|
||||
public function testLintCorrectFiles()
|
||||
{
|
||||
$tester = $this->createCommandTester();
|
||||
$filename1 = $this->createFile();
|
||||
$filename2 = $this->createFile();
|
||||
|
||||
$tester->execute(
|
||||
array('filename' => array($filename1, $filename2)),
|
||||
array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)
|
||||
);
|
||||
|
||||
$this->assertEquals(0, $tester->getStatusCode(), 'Returns 0 in case of success');
|
||||
$this->assertContains('OK', trim($tester->getDisplay()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideStrictFilenames
|
||||
*/
|
||||
public function testStrictFilenames($requireStrictFileNames, $fileNamePattern, $targetLanguage, $mustFail)
|
||||
{
|
||||
$tester = $this->createCommandTester($requireStrictFileNames);
|
||||
$filename = $this->createFile('note', $targetLanguage, $fileNamePattern);
|
||||
|
||||
$tester->execute(
|
||||
array('filename' => $filename),
|
||||
array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)
|
||||
);
|
||||
|
||||
$this->assertEquals($mustFail ? 1 : 0, $tester->getStatusCode());
|
||||
$this->assertContains($mustFail ? '[WARNING] 0 XLIFF files have valid syntax and 1 contain errors.' : '[OK] All 1 XLIFF files contain valid syntax.', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testLintIncorrectXmlSyntax()
|
||||
{
|
||||
$tester = $this->createCommandTester();
|
||||
@@ -59,7 +91,7 @@ class XliffLintCommandTest extends TestCase
|
||||
$tester->execute(array('filename' => $filename), array('decorated' => false));
|
||||
|
||||
$this->assertEquals(1, $tester->getStatusCode(), 'Returns 1 in case of error');
|
||||
$this->assertContains('There is a mismatch between the file extension ("en.xlf") and the "es" value used in the "target-language" attribute of the file.', trim($tester->getDisplay()));
|
||||
$this->assertContains('There is a mismatch between the language included in the file name ("messages.en.xlf") and the "es" value used in the "target-language" attribute of the file.', trim($tester->getDisplay()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,7 +134,7 @@ EOF;
|
||||
/**
|
||||
* @return string Path to the new file
|
||||
*/
|
||||
private function createFile($sourceContent = 'note', $targetLanguage = 'en')
|
||||
private function createFile($sourceContent = 'note', $targetLanguage = 'en', $fileNamePattern = 'messages.%locale%.xlf')
|
||||
{
|
||||
$xliffContent = <<<XLIFF
|
||||
<?xml version="1.0"?>
|
||||
@@ -118,7 +150,7 @@ EOF;
|
||||
</xliff>
|
||||
XLIFF;
|
||||
|
||||
$filename = sprintf('%s/translation-xliff-lint-test/messages.en.xlf', sys_get_temp_dir());
|
||||
$filename = sprintf('%s/translation-xliff-lint-test/%s', sys_get_temp_dir(), str_replace('%locale%', 'en', $fileNamePattern));
|
||||
file_put_contents($filename, $xliffContent);
|
||||
|
||||
$this->files[] = $filename;
|
||||
@@ -129,11 +161,11 @@ XLIFF;
|
||||
/**
|
||||
* @return CommandTester
|
||||
*/
|
||||
private function createCommandTester($application = null)
|
||||
private function createCommandTester($requireStrictFileNames = true, $application = null)
|
||||
{
|
||||
if (!$application) {
|
||||
$application = new Application();
|
||||
$application->add(new XliffLintCommand());
|
||||
$application->add(new XliffLintCommand(null, null, null, $requireStrictFileNames));
|
||||
}
|
||||
|
||||
$command = $application->find('lint:xliff');
|
||||
@@ -160,4 +192,16 @@ XLIFF;
|
||||
}
|
||||
rmdir(sys_get_temp_dir().'/translation-xliff-lint-test');
|
||||
}
|
||||
|
||||
public function provideStrictFilenames()
|
||||
{
|
||||
yield array(false, 'messages.%locale%.xlf', 'en', false);
|
||||
yield array(false, 'messages.%locale%.xlf', 'es', true);
|
||||
yield array(false, '%locale%.messages.xlf', 'en', false);
|
||||
yield array(false, '%locale%.messages.xlf', 'es', true);
|
||||
yield array(true, 'messages.%locale%.xlf', 'en', false);
|
||||
yield array(true, 'messages.%locale%.xlf', 'es', true);
|
||||
yield array(true, '%locale%.messages.xlf', 'en', true);
|
||||
yield array(true, '%locale%.messages.xlf', 'es', true);
|
||||
}
|
||||
}
|
||||
|
@@ -42,85 +42,85 @@ class TranslationDataCollectorTest extends TestCase
|
||||
{
|
||||
$collectedMessages = array(
|
||||
array(
|
||||
'id' => 'foo',
|
||||
'translation' => 'foo (en)',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_DEFINED,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
'id' => 'foo',
|
||||
'translation' => 'foo (en)',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_DEFINED,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
),
|
||||
array(
|
||||
'id' => 'bar',
|
||||
'translation' => 'bar (fr)',
|
||||
'locale' => 'fr',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
'id' => 'bar',
|
||||
'translation' => 'bar (fr)',
|
||||
'locale' => 'fr',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
),
|
||||
array(
|
||||
'id' => 'choice',
|
||||
'translation' => 'choice',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'parameters' => array('%count%' => 3),
|
||||
'transChoiceNumber' => 3,
|
||||
'id' => 'choice',
|
||||
'translation' => 'choice',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'parameters' => array('%count%' => 3),
|
||||
'transChoiceNumber' => 3,
|
||||
),
|
||||
array(
|
||||
'id' => 'choice',
|
||||
'translation' => 'choice',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'parameters' => array('%count%' => 3),
|
||||
'transChoiceNumber' => 3,
|
||||
'id' => 'choice',
|
||||
'translation' => 'choice',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'parameters' => array('%count%' => 3),
|
||||
'transChoiceNumber' => 3,
|
||||
),
|
||||
array(
|
||||
'id' => 'choice',
|
||||
'translation' => 'choice',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'parameters' => array('%count%' => 4, '%foo%' => 'bar'),
|
||||
'transChoiceNumber' => 4,
|
||||
'id' => 'choice',
|
||||
'translation' => 'choice',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'parameters' => array('%count%' => 4, '%foo%' => 'bar'),
|
||||
'transChoiceNumber' => 4,
|
||||
),
|
||||
);
|
||||
$expectedMessages = array(
|
||||
array(
|
||||
'id' => 'foo',
|
||||
'translation' => 'foo (en)',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_DEFINED,
|
||||
'count' => 1,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
'id' => 'foo',
|
||||
'translation' => 'foo (en)',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_DEFINED,
|
||||
'count' => 1,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
),
|
||||
array(
|
||||
'id' => 'bar',
|
||||
'translation' => 'bar (fr)',
|
||||
'locale' => 'fr',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
|
||||
'count' => 1,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
'id' => 'bar',
|
||||
'translation' => 'bar (fr)',
|
||||
'locale' => 'fr',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
|
||||
'count' => 1,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
),
|
||||
array(
|
||||
'id' => 'choice',
|
||||
'translation' => 'choice',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'count' => 3,
|
||||
'parameters' => array(
|
||||
array('%count%' => 3),
|
||||
array('%count%' => 3),
|
||||
array('%count%' => 4, '%foo%' => 'bar'),
|
||||
),
|
||||
'transChoiceNumber' => 3,
|
||||
'id' => 'choice',
|
||||
'translation' => 'choice',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'count' => 3,
|
||||
'parameters' => array(
|
||||
array('%count%' => 3),
|
||||
array('%count%' => 3),
|
||||
array('%count%' => 4, '%foo%' => 'bar'),
|
||||
),
|
||||
'transChoiceNumber' => 3,
|
||||
),
|
||||
);
|
||||
|
||||
|
@@ -25,56 +25,80 @@ class DataCollectorTranslatorTest extends TestCase
|
||||
|
||||
$collector->trans('foo');
|
||||
$collector->trans('bar');
|
||||
$collector->transChoice('choice', 0);
|
||||
$collector->trans('choice', array('%count%' => 0));
|
||||
$collector->trans('bar_ru');
|
||||
$collector->trans('bar_ru', array('foo' => 'bar'));
|
||||
|
||||
$expectedMessages = array();
|
||||
$expectedMessages[] = array(
|
||||
'id' => 'foo',
|
||||
'translation' => 'foo (en)',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_DEFINED,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
'id' => 'foo',
|
||||
'translation' => 'foo (en)',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_DEFINED,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
);
|
||||
$expectedMessages[] = array(
|
||||
'id' => 'bar',
|
||||
'translation' => 'bar (fr)',
|
||||
'locale' => 'fr',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
'id' => 'bar',
|
||||
'translation' => 'bar (fr)',
|
||||
'locale' => 'fr',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
);
|
||||
$expectedMessages[] = array(
|
||||
'id' => 'choice',
|
||||
'translation' => 'choice',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'parameters' => array('%count%' => 0),
|
||||
'transChoiceNumber' => 0,
|
||||
);
|
||||
$expectedMessages[] = array(
|
||||
'id' => 'bar_ru',
|
||||
'translation' => 'bar (ru)',
|
||||
'locale' => 'ru',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
);
|
||||
$expectedMessages[] = array(
|
||||
'id' => 'bar_ru',
|
||||
'translation' => 'bar (ru)',
|
||||
'locale' => 'ru',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
|
||||
'parameters' => array('foo' => 'bar'),
|
||||
'transChoiceNumber' => null,
|
||||
);
|
||||
|
||||
$this->assertEquals($expectedMessages, $collector->getCollectedMessages());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testCollectMessagesTransChoice()
|
||||
{
|
||||
$collector = $this->createCollector();
|
||||
$collector->setFallbackLocales(array('fr', 'ru'));
|
||||
$collector->transChoice('choice', 0);
|
||||
|
||||
$expectedMessages = array();
|
||||
|
||||
$expectedMessages[] = array(
|
||||
'id' => 'choice',
|
||||
'translation' => 'choice',
|
||||
'locale' => 'en',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'parameters' => array(),
|
||||
'parameters' => array('%count%' => 0),
|
||||
'transChoiceNumber' => 0,
|
||||
);
|
||||
$expectedMessages[] = array(
|
||||
'id' => 'bar_ru',
|
||||
'translation' => 'bar (ru)',
|
||||
'locale' => 'ru',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
|
||||
'parameters' => array(),
|
||||
'transChoiceNumber' => null,
|
||||
);
|
||||
$expectedMessages[] = array(
|
||||
'id' => 'bar_ru',
|
||||
'translation' => 'bar (ru)',
|
||||
'locale' => 'ru',
|
||||
'domain' => 'messages',
|
||||
'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
|
||||
'parameters' => array('foo' => 'bar'),
|
||||
'transChoiceNumber' => null,
|
||||
);
|
||||
|
||||
$this->assertEquals($expectedMessages, $collector->getCollectedMessages());
|
||||
}
|
||||
|
@@ -32,6 +32,30 @@ class FileDumperTest extends TestCase
|
||||
@unlink($tempDir.'/messages.en.concrete');
|
||||
}
|
||||
|
||||
public function testDumpIntl()
|
||||
{
|
||||
$tempDir = sys_get_temp_dir();
|
||||
|
||||
$catalogue = new MessageCatalogue('en');
|
||||
$catalogue->add(array('foo' => 'bar'), 'd1');
|
||||
$catalogue->add(array('bar' => 'foo'), 'd1+intl-icu');
|
||||
$catalogue->add(array('bar' => 'foo'), 'd2+intl-icu');
|
||||
|
||||
$dumper = new ConcreteFileDumper();
|
||||
@unlink($tempDir.'/d2.en.concrete');
|
||||
$dumper->dump($catalogue, array('path' => $tempDir));
|
||||
|
||||
$this->assertStringEqualsFile($tempDir.'/d1.en.concrete', 'foo=bar');
|
||||
@unlink($tempDir.'/d1.en.concrete');
|
||||
|
||||
$this->assertStringEqualsFile($tempDir.'/d1+intl-icu.en.concrete', 'bar=foo');
|
||||
@unlink($tempDir.'/d1+intl-icu.en.concrete');
|
||||
|
||||
$this->assertFileNotExists($tempDir.'/d2.en.concrete');
|
||||
$this->assertStringEqualsFile($tempDir.'/d2+intl-icu.en.concrete', 'bar=foo');
|
||||
@unlink($tempDir.'/d2+intl-icu.en.concrete');
|
||||
}
|
||||
|
||||
public function testDumpCreatesNestedDirectoriesAndFile()
|
||||
{
|
||||
$tempDir = sys_get_temp_dir();
|
||||
@@ -56,7 +80,7 @@ class ConcreteFileDumper extends FileDumper
|
||||
{
|
||||
public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
|
||||
{
|
||||
return '';
|
||||
return http_build_query($messages->all($domain), '', '&');
|
||||
}
|
||||
|
||||
protected function getExtension()
|
||||
|
96
vendor/symfony/translation/Tests/Formatter/IntlFormatterTest.php
vendored
Normal file
96
vendor/symfony/translation/Tests/Formatter/IntlFormatterTest.php
vendored
Normal 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\Translation\Tests\Formatter;
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\Formatter\IntlFormatter;
|
||||
use Symfony\Component\Translation\Formatter\IntlFormatterInterface;
|
||||
|
||||
/**
|
||||
* @requires extension intl
|
||||
*/
|
||||
class IntlFormatterTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideDataForFormat
|
||||
*/
|
||||
public function testFormat($expected, $message, $arguments)
|
||||
{
|
||||
$this->assertEquals($expected, trim((new IntlFormatter())->formatIntl($message, 'en', $arguments)));
|
||||
}
|
||||
|
||||
public function testInvalidFormat()
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
(new IntlFormatter())->formatIntl('{foo', 'en', array(2));
|
||||
}
|
||||
|
||||
public function testFormatWithNamedArguments()
|
||||
{
|
||||
if (version_compare(INTL_ICU_VERSION, '4.8', '<')) {
|
||||
$this->markTestSkipped('Format with named arguments can only be run with ICU 4.8 or higher and PHP >= 5.5');
|
||||
}
|
||||
|
||||
$chooseMessage = <<<'_MSG_'
|
||||
{gender_of_host, select,
|
||||
female {{num_guests, plural, offset:1
|
||||
=0 {{host} does not give a party.}
|
||||
=1 {{host} invites {guest} to her party.}
|
||||
=2 {{host} invites {guest} and one other person to her party.}
|
||||
other {{host} invites {guest} as one of the # people invited to her party.}}}
|
||||
male {{num_guests, plural, offset:1
|
||||
=0 {{host} does not give a party.}
|
||||
=1 {{host} invites {guest} to his party.}
|
||||
=2 {{host} invites {guest} and one other person to his party.}
|
||||
other {{host} invites {guest} as one of the # people invited to his party.}}}
|
||||
other {{num_guests, plural, offset:1
|
||||
=0 {{host} does not give a party.}
|
||||
=1 {{host} invites {guest} to their party.}
|
||||
=2 {{host} invites {guest} and one other person to their party.}
|
||||
other {{host} invites {guest} as one of the # people invited to their party.}}}}
|
||||
_MSG_;
|
||||
|
||||
$message = (new IntlFormatter())->formatIntl($chooseMessage, 'en', array(
|
||||
'gender_of_host' => 'male',
|
||||
'num_guests' => 10,
|
||||
'host' => 'Fabien',
|
||||
'guest' => 'Guilherme',
|
||||
));
|
||||
|
||||
$this->assertEquals('Fabien invites Guilherme as one of the 9 people invited to his party.', $message);
|
||||
}
|
||||
|
||||
public function provideDataForFormat()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'There is one apple',
|
||||
'There is one apple',
|
||||
array(),
|
||||
),
|
||||
array(
|
||||
'4,560 monkeys on 123 trees make 37.073 monkeys per tree',
|
||||
'{0,number,integer} monkeys on {1,number,integer} trees make {2,number} monkeys per tree',
|
||||
array(4560, 123, 4560 / 123),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function testPercentsAndBracketsAreTrimmed()
|
||||
{
|
||||
$formatter = new IntlFormatter();
|
||||
$this->assertInstanceof(IntlFormatterInterface::class, $formatter);
|
||||
$this->assertSame('Hello Fab', $formatter->formatIntl('Hello {name}', 'en', array('name' => 'Fab')));
|
||||
$this->assertSame('Hello Fab', $formatter->formatIntl('Hello {name}', 'en', array('%name%' => 'Fab')));
|
||||
$this->assertSame('Hello Fab', $formatter->formatIntl('Hello {name}', 'en', array('{{ name }}' => 'Fab')));
|
||||
}
|
||||
}
|
@@ -26,6 +26,7 @@ class MessageFormatterTest extends TestCase
|
||||
|
||||
/**
|
||||
* @dataProvider getTransChoiceMessages
|
||||
* @group legacy
|
||||
*/
|
||||
public function testFormatPlural($expected, $message, $number, $parameters)
|
||||
{
|
||||
|
@@ -11,86 +11,13 @@
|
||||
|
||||
namespace Symfony\Component\Translation\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Intl\Util\IntlTestHelper;
|
||||
use Symfony\Component\Translation\IdentityTranslator;
|
||||
use Symfony\Contracts\Tests\Translation\TranslatorTest;
|
||||
|
||||
class IdentityTranslatorTest extends TestCase
|
||||
class IdentityTranslatorTest extends TranslatorTest
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTransTests
|
||||
*/
|
||||
public function testTrans($expected, $id, $parameters)
|
||||
public function getTranslator()
|
||||
{
|
||||
$translator = new IdentityTranslator();
|
||||
|
||||
$this->assertEquals($expected, $translator->trans($id, $parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTransChoiceTests
|
||||
*/
|
||||
public function testTransChoiceWithExplicitLocale($expected, $id, $number, $parameters)
|
||||
{
|
||||
$translator = new IdentityTranslator();
|
||||
$translator->setLocale('en');
|
||||
|
||||
$this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTransChoiceTests
|
||||
*/
|
||||
public function testTransChoiceWithDefaultLocale($expected, $id, $number, $parameters)
|
||||
{
|
||||
\Locale::setDefault('en');
|
||||
|
||||
$translator = new IdentityTranslator();
|
||||
|
||||
$this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
|
||||
}
|
||||
|
||||
public function testGetSetLocale()
|
||||
{
|
||||
$translator = new IdentityTranslator();
|
||||
$translator->setLocale('en');
|
||||
|
||||
$this->assertEquals('en', $translator->getLocale());
|
||||
}
|
||||
|
||||
public function testGetLocaleReturnsDefaultLocaleIfNotSet()
|
||||
{
|
||||
// in order to test with "pt_BR"
|
||||
IntlTestHelper::requireFullIntl($this, false);
|
||||
|
||||
$translator = new IdentityTranslator();
|
||||
|
||||
\Locale::setDefault('en');
|
||||
$this->assertEquals('en', $translator->getLocale());
|
||||
|
||||
\Locale::setDefault('pt_BR');
|
||||
$this->assertEquals('pt_BR', $translator->getLocale());
|
||||
}
|
||||
|
||||
public function getTransTests()
|
||||
{
|
||||
return array(
|
||||
array('Symfony is great!', 'Symfony is great!', array()),
|
||||
array('Symfony is awesome!', 'Symfony is %what%!', array('%what%' => 'awesome')),
|
||||
);
|
||||
}
|
||||
|
||||
public function getTransChoiceTests()
|
||||
{
|
||||
return array(
|
||||
array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0, array('%count%' => 0)),
|
||||
array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1, array('%count%' => 1)),
|
||||
array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10, array('%count%' => 10)),
|
||||
array('There are 0 apples', 'There is 1 apple|There are %count% apples', 0, array('%count%' => 0)),
|
||||
array('There is 1 apple', 'There is 1 apple|There are %count% apples', 1, array('%count%' => 1)),
|
||||
array('There are 10 apples', 'There is 1 apple|There are %count% apples', 10, array('%count%' => 10)),
|
||||
// custom validation messages may be coded with a fixed value
|
||||
array('There are 2 apples', 'There are 2 apples', 2, array('%count%' => 2)),
|
||||
);
|
||||
return new IdentityTranslator();
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,9 @@ namespace Symfony\Component\Translation\Tests;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Translation\Interval;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
class IntervalTest extends TestCase
|
||||
{
|
||||
/**
|
||||
|
@@ -66,7 +66,7 @@ class XliffFileLoaderTest extends TestCase
|
||||
$loader = new XliffFileLoader();
|
||||
$catalogue = $loader->load(__DIR__.'/../fixtures/resname.xlf', 'en', 'domain1');
|
||||
|
||||
$this->assertEquals(array('foo' => 'bar', 'bar' => 'baz', 'baz' => 'foo'), $catalogue->all('domain1'));
|
||||
$this->assertEquals(array('foo' => 'bar', 'bar' => 'baz', 'baz' => 'foo', 'qux' => 'qux source'), $catalogue->all('domain1'));
|
||||
}
|
||||
|
||||
public function testIncompleteResource()
|
||||
|
@@ -21,17 +21,19 @@ class LoggingTranslatorTest extends TestCase
|
||||
public function testTransWithNoTranslationIsLogged()
|
||||
{
|
||||
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||
$logger->expects($this->exactly(2))
|
||||
$logger->expects($this->exactly(1))
|
||||
->method('warning')
|
||||
->with('Translation not found.')
|
||||
;
|
||||
|
||||
$translator = new Translator('ar');
|
||||
$loggableTranslator = new LoggingTranslator($translator, $logger);
|
||||
$loggableTranslator->transChoice('some_message2', 10, array('%count%' => 10));
|
||||
$loggableTranslator->trans('bar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testTransChoiceFallbackIsLogged()
|
||||
{
|
||||
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||
@@ -47,4 +49,20 @@ class LoggingTranslatorTest extends TestCase
|
||||
$loggableTranslator = new LoggingTranslator($translator, $logger);
|
||||
$loggableTranslator->transChoice('some_message2', 10, array('%count%' => 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testTransChoiceWithNoTranslationIsLogged()
|
||||
{
|
||||
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||
$logger->expects($this->exactly(1))
|
||||
->method('warning')
|
||||
->with('Translation not found.')
|
||||
;
|
||||
|
||||
$translator = new Translator('ar');
|
||||
$loggableTranslator = new LoggingTranslator($translator, $logger);
|
||||
$loggableTranslator->transChoice('some_message2', 10, array('%count%' => 10));
|
||||
}
|
||||
}
|
||||
|
@@ -25,9 +25,9 @@ class MessageCatalogueTest extends TestCase
|
||||
|
||||
public function testGetDomains()
|
||||
{
|
||||
$catalogue = new MessageCatalogue('en', array('domain1' => array(), 'domain2' => array()));
|
||||
$catalogue = new MessageCatalogue('en', array('domain1' => array(), 'domain2' => array(), 'domain2+intl-icu' => array(), 'domain3+intl-icu' => array()));
|
||||
|
||||
$this->assertEquals(array('domain1', 'domain2'), $catalogue->getDomains());
|
||||
$this->assertEquals(array('domain1', 'domain2', 'domain3'), $catalogue->getDomains());
|
||||
}
|
||||
|
||||
public function testAll()
|
||||
@@ -37,24 +37,43 @@ class MessageCatalogueTest extends TestCase
|
||||
$this->assertEquals(array('foo' => 'foo'), $catalogue->all('domain1'));
|
||||
$this->assertEquals(array(), $catalogue->all('domain88'));
|
||||
$this->assertEquals($messages, $catalogue->all());
|
||||
|
||||
$messages = array('domain1+intl-icu' => array('foo' => 'bar')) + $messages + array(
|
||||
'domain2+intl-icu' => array('bar' => 'foo'),
|
||||
'domain3+intl-icu' => array('biz' => 'biz'),
|
||||
);
|
||||
$catalogue = new MessageCatalogue('en', $messages);
|
||||
|
||||
$this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
|
||||
$this->assertEquals(array('bar' => 'foo'), $catalogue->all('domain2'));
|
||||
$this->assertEquals(array('biz' => 'biz'), $catalogue->all('domain3'));
|
||||
|
||||
$messages = array(
|
||||
'domain1' => array('foo' => 'bar'),
|
||||
'domain2' => array('bar' => 'foo'),
|
||||
'domain3' => array('biz' => 'biz'),
|
||||
);
|
||||
$this->assertEquals($messages, $catalogue->all());
|
||||
}
|
||||
|
||||
public function testHas()
|
||||
{
|
||||
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
|
||||
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2+intl-icu' => array('bar' => 'bar')));
|
||||
|
||||
$this->assertTrue($catalogue->has('foo', 'domain1'));
|
||||
$this->assertTrue($catalogue->has('bar', 'domain2'));
|
||||
$this->assertFalse($catalogue->has('bar', 'domain1'));
|
||||
$this->assertFalse($catalogue->has('foo', 'domain88'));
|
||||
}
|
||||
|
||||
public function testGetSet()
|
||||
{
|
||||
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
|
||||
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar'), 'domain2+intl-icu' => array('bar' => 'foo')));
|
||||
$catalogue->set('foo1', 'foo1', 'domain1');
|
||||
|
||||
$this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
|
||||
$this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));
|
||||
$this->assertEquals('foo', $catalogue->get('bar', 'domain2'));
|
||||
}
|
||||
|
||||
public function testAdd()
|
||||
@@ -75,7 +94,7 @@ class MessageCatalogueTest extends TestCase
|
||||
|
||||
public function testReplace()
|
||||
{
|
||||
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
|
||||
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain1+intl-icu' => array('bar' => 'bar')));
|
||||
$catalogue->replace($messages = array('foo1' => 'foo1'), 'domain1');
|
||||
|
||||
$this->assertEquals($messages, $catalogue->all('domain1'));
|
||||
@@ -89,16 +108,18 @@ class MessageCatalogueTest extends TestCase
|
||||
$r1 = $this->getMockBuilder('Symfony\Component\Config\Resource\ResourceInterface')->getMock();
|
||||
$r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));
|
||||
|
||||
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
|
||||
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo')));
|
||||
$catalogue->addResource($r);
|
||||
|
||||
$catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo1' => 'foo1')));
|
||||
$catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo1' => 'foo1'), 'domain2+intl-icu' => array('bar' => 'bar')));
|
||||
$catalogue1->addResource($r1);
|
||||
|
||||
$catalogue->addCatalogue($catalogue1);
|
||||
|
||||
$this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
|
||||
$this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));
|
||||
$this->assertEquals('bar', $catalogue->get('bar', 'domain2'));
|
||||
$this->assertEquals('bar', $catalogue->get('bar', 'domain2+intl-icu'));
|
||||
|
||||
$this->assertEquals(array($r, $r1), $catalogue->getResources());
|
||||
}
|
||||
|
@@ -14,6 +14,9 @@ namespace Symfony\Component\Translation\Tests;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Translation\MessageSelector;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
class MessageSelectorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
|
@@ -26,6 +26,8 @@ use Symfony\Component\Translation\PluralizationRules;
|
||||
* The goal to cover all languages is to far fetched so this test case is smaller.
|
||||
*
|
||||
* @author Clemens Tolboom clemens@build2be.nl
|
||||
*
|
||||
* @group legacy
|
||||
*/
|
||||
class PluralizationRulesTest extends TestCase
|
||||
{
|
||||
|
@@ -24,7 +24,7 @@ class TranslatorCacheTest extends TestCase
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->tmpDir = sys_get_temp_dir().'/sf2_translation';
|
||||
$this->tmpDir = sys_get_temp_dir().'/sf_translation';
|
||||
$this->deleteTmpDir();
|
||||
}
|
||||
|
||||
@@ -66,13 +66,17 @@ class TranslatorCacheTest extends TestCase
|
||||
$translator = new Translator($locale, null, $this->tmpDir, $debug);
|
||||
$translator->addLoader($format, new ArrayLoader());
|
||||
$translator->addResource($format, array($msgid => 'OK'), $locale);
|
||||
$translator->addResource($format, array($msgid.'+intl' => 'OK'), $locale, 'messages+intl-icu');
|
||||
$translator->trans($msgid);
|
||||
$translator->trans($msgid.'+intl', array(), 'messages+intl-icu');
|
||||
|
||||
// Try again and see we get a valid result whilst no loader can be used
|
||||
$translator = new Translator($locale, null, $this->tmpDir, $debug);
|
||||
$translator->addLoader($format, $this->createFailingLoader());
|
||||
$translator->addResource($format, array($msgid => 'OK'), $locale);
|
||||
$translator->addResource($format, array($msgid.'+intl' => 'OK'), $locale, 'messages+intl-icu');
|
||||
$this->assertEquals('OK', $translator->trans($msgid), '-> caching does not work in '.($debug ? 'debug' : 'production'));
|
||||
$this->assertEquals('OK', $translator->trans($msgid.'+intl', array(), 'messages+intl-icu'));
|
||||
}
|
||||
|
||||
public function testCatalogueIsReloadedWhenResourcesAreNoLongerFresh()
|
||||
@@ -212,6 +216,7 @@ class TranslatorCacheTest extends TestCase
|
||||
$translator->addResource('array', array('foo' => 'foo (a)'), 'a');
|
||||
$translator->addResource('array', array('foo' => 'foo (b)'), 'b');
|
||||
$translator->addResource('array', array('bar' => 'bar (b)'), 'b');
|
||||
$translator->addResource('array', array('baz' => 'baz (b)'), 'b', 'messages+intl-icu');
|
||||
|
||||
$catalogue = $translator->getCatalogue('a');
|
||||
$this->assertFalse($catalogue->defines('bar')); // Sure, the "a" catalogue does not contain that message.
|
||||
@@ -230,12 +235,14 @@ class TranslatorCacheTest extends TestCase
|
||||
$translator->addResource('array', array('foo' => 'foo (a)'), 'a');
|
||||
$translator->addResource('array', array('foo' => 'foo (b)'), 'b');
|
||||
$translator->addResource('array', array('bar' => 'bar (b)'), 'b');
|
||||
$translator->addResource('array', array('baz' => 'baz (b)'), 'b', 'messages+intl-icu');
|
||||
|
||||
$catalogue = $translator->getCatalogue('a');
|
||||
$this->assertFalse($catalogue->defines('bar'));
|
||||
|
||||
$fallback = $catalogue->getFallbackCatalogue();
|
||||
$this->assertTrue($fallback->defines('foo'));
|
||||
$this->assertTrue($fallback->defines('baz', 'messages+intl-icu'));
|
||||
}
|
||||
|
||||
public function testRefreshCacheWhenResourcesAreNoLongerFresh()
|
||||
|
@@ -234,6 +234,42 @@ class TranslatorTest extends TestCase
|
||||
$this->assertEquals('bar', $translator->trans('foo', array(), 'resources'));
|
||||
}
|
||||
|
||||
public function testTransWithIcuFallbackLocale()
|
||||
{
|
||||
$translator = new Translator('en_GB');
|
||||
$translator->addLoader('array', new ArrayLoader());
|
||||
$translator->addResource('array', array('foo' => 'foofoo'), 'en_GB');
|
||||
$translator->addResource('array', array('bar' => 'foobar'), 'en_001');
|
||||
$translator->addResource('array', array('baz' => 'foobaz'), 'en');
|
||||
$this->assertSame('foofoo', $translator->trans('foo'));
|
||||
$this->assertSame('foobar', $translator->trans('bar'));
|
||||
$this->assertSame('foobaz', $translator->trans('baz'));
|
||||
}
|
||||
|
||||
public function testTransWithIcuVariantFallbackLocale()
|
||||
{
|
||||
$translator = new Translator('en_GB_scouse');
|
||||
$translator->addLoader('array', new ArrayLoader());
|
||||
$translator->addResource('array', array('foo' => 'foofoo'), 'en_GB_scouse');
|
||||
$translator->addResource('array', array('bar' => 'foobar'), 'en_GB');
|
||||
$translator->addResource('array', array('baz' => 'foobaz'), 'en_001');
|
||||
$translator->addResource('array', array('qux' => 'fooqux'), 'en');
|
||||
$this->assertSame('foofoo', $translator->trans('foo'));
|
||||
$this->assertSame('foobar', $translator->trans('bar'));
|
||||
$this->assertSame('foobaz', $translator->trans('baz'));
|
||||
$this->assertSame('fooqux', $translator->trans('qux'));
|
||||
}
|
||||
|
||||
public function testTransWithIcuRootFallbackLocale()
|
||||
{
|
||||
$translator = new Translator('az_Cyrl');
|
||||
$translator->addLoader('array', new ArrayLoader());
|
||||
$translator->addResource('array', array('foo' => 'foofoo'), 'az_Cyrl');
|
||||
$translator->addResource('array', array('bar' => 'foobar'), 'az');
|
||||
$this->assertSame('foofoo', $translator->trans('foo'));
|
||||
$this->assertSame('bar', $translator->trans('bar'));
|
||||
}
|
||||
|
||||
public function testTransWithFallbackLocaleBis()
|
||||
{
|
||||
$translator = new Translator('en_US');
|
||||
@@ -357,6 +393,7 @@ class TranslatorTest extends TestCase
|
||||
|
||||
/**
|
||||
* @dataProvider getTransChoiceTests
|
||||
* @group legacy
|
||||
*/
|
||||
public function testTransChoice($expected, $id, $translation, $number, $parameters, $locale, $domain)
|
||||
{
|
||||
@@ -370,6 +407,7 @@ class TranslatorTest extends TestCase
|
||||
/**
|
||||
* @dataProvider getInvalidLocalesTests
|
||||
* @expectedException \Symfony\Component\Translation\Exception\InvalidArgumentException
|
||||
* @group legacy
|
||||
*/
|
||||
public function testTransChoiceInvalidLocale($locale)
|
||||
{
|
||||
@@ -382,6 +420,7 @@ class TranslatorTest extends TestCase
|
||||
|
||||
/**
|
||||
* @dataProvider getValidLocalesTests
|
||||
* @group legacy
|
||||
*/
|
||||
public function testTransChoiceValidLocale($locale)
|
||||
{
|
||||
@@ -463,7 +502,7 @@ class TranslatorTest extends TestCase
|
||||
array('Il y a 0 pomme', new StringClass('{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples'), '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array(), 'fr', ''),
|
||||
|
||||
// Override %count% with a custom value
|
||||
array('Il y a quelques pommes', 'one: There is one apple|more: There are %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 2, array('%count%' => 'quelques'), 'fr', ''),
|
||||
array('Il y a quelques pommes', 'one: There is one apple|more: There are %count% apples', 'one: Il y a %count% pomme|more: Il y a quelques pommes', 2, array('%count%' => 'quelques'), 'fr', ''),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -501,6 +540,24 @@ class TranslatorTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension intl
|
||||
*/
|
||||
public function testIntlFormattedDomain()
|
||||
{
|
||||
$translator = new Translator('en');
|
||||
$translator->addLoader('array', new ArrayLoader());
|
||||
|
||||
$translator->addResource('array', array('some_message' => 'Hello %name%'), 'en');
|
||||
$this->assertSame('Hello Bob', $translator->trans('some_message', array('%name%' => 'Bob')));
|
||||
|
||||
$translator->addResource('array', array('some_message' => 'Hi {name}'), 'en', 'messages+intl-icu');
|
||||
$this->assertSame('Hi Bob', $translator->trans('some_message', array('%name%' => 'Bob')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testTransChoiceFallback()
|
||||
{
|
||||
$translator = new Translator('ru');
|
||||
@@ -511,6 +568,9 @@ class TranslatorTest extends TestCase
|
||||
$this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testTransChoiceFallbackBis()
|
||||
{
|
||||
$translator = new Translator('ru');
|
||||
@@ -521,6 +581,9 @@ class TranslatorTest extends TestCase
|
||||
$this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testTransChoiceFallbackWithNoTranslation()
|
||||
{
|
||||
$translator = new Translator('ru');
|
||||
|
@@ -14,6 +14,9 @@
|
||||
<source>baz</source>
|
||||
<target>foo</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4" resname="qux">
|
||||
<source>qux source</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
86
vendor/symfony/translation/Translator.php
vendored
86
vendor/symfony/translation/Translator.php
vendored
@@ -19,14 +19,17 @@ use Symfony\Component\Translation\Exception\LogicException;
|
||||
use Symfony\Component\Translation\Exception\NotFoundResourceException;
|
||||
use Symfony\Component\Translation\Exception\RuntimeException;
|
||||
use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface;
|
||||
use Symfony\Component\Translation\Formatter\IntlFormatterInterface;
|
||||
use Symfony\Component\Translation\Formatter\MessageFormatter;
|
||||
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
|
||||
use Symfony\Component\Translation\Loader\LoaderInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Translator implements TranslatorInterface, TranslatorBagInterface
|
||||
class Translator implements LegacyTranslatorInterface, TranslatorInterface, TranslatorBagInterface
|
||||
{
|
||||
/**
|
||||
* @var MessageCatalogueInterface[]
|
||||
@@ -73,6 +76,13 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
|
||||
*/
|
||||
private $configCacheFactory;
|
||||
|
||||
/**
|
||||
* @var array|null
|
||||
*/
|
||||
private $parentLocales;
|
||||
|
||||
private $hasIntlFormatter;
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException If a locale contains invalid characters
|
||||
*/
|
||||
@@ -87,6 +97,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
|
||||
$this->formatter = $formatter;
|
||||
$this->cacheDir = $cacheDir;
|
||||
$this->debug = $debug;
|
||||
$this->hasIntlFormatter = $formatter instanceof IntlFormatterInterface;
|
||||
}
|
||||
|
||||
public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
|
||||
@@ -171,7 +182,9 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
|
||||
/**
|
||||
* Gets the fallback locales.
|
||||
*
|
||||
* @return array $locales The fallback locales
|
||||
* @internal since Symfony 4.2
|
||||
*
|
||||
* @return array The fallback locales
|
||||
*/
|
||||
public function getFallbackLocales()
|
||||
{
|
||||
@@ -187,14 +200,34 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
|
||||
$domain = 'messages';
|
||||
}
|
||||
|
||||
return $this->formatter->format($this->getCatalogue($locale)->get((string) $id, $domain), $locale, $parameters);
|
||||
$id = (string) $id;
|
||||
$catalogue = $this->getCatalogue($locale);
|
||||
$locale = $catalogue->getLocale();
|
||||
while (!$catalogue->defines($id, $domain)) {
|
||||
if ($cat = $catalogue->getFallbackCatalogue()) {
|
||||
$catalogue = $cat;
|
||||
$locale = $catalogue->getLocale();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->hasIntlFormatter && $catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
|
||||
return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, $parameters);
|
||||
}
|
||||
|
||||
return $this->formatter->format($catalogue->get($id, $domain), $locale, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
|
||||
*/
|
||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%%count%%" parameter.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
if (!$this->formatter instanceof ChoiceMessageFormatterInterface) {
|
||||
throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', \get_class($this->formatter)));
|
||||
}
|
||||
@@ -215,6 +248,10 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->hasIntlFormatter && $catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
|
||||
return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, array('%count%' => $number) + $parameters);
|
||||
}
|
||||
|
||||
return $this->formatter->choiceFormat($catalogue->get($id, $domain), $number, $locale, $parameters);
|
||||
}
|
||||
|
||||
@@ -316,7 +353,7 @@ return \$catalogue;
|
||||
EOF
|
||||
,
|
||||
$locale,
|
||||
var_export($this->catalogues[$locale]->all(), true),
|
||||
var_export($this->getAllMessages($this->catalogues[$locale]), true),
|
||||
$fallbackContent
|
||||
);
|
||||
|
||||
@@ -342,7 +379,7 @@ EOF
|
||||
,
|
||||
$fallbackSuffix,
|
||||
$fallback,
|
||||
var_export($fallbackCatalogue->all(), true),
|
||||
var_export($this->getAllMessages($fallbackCatalogue), true),
|
||||
$currentSuffix,
|
||||
$fallbackSuffix
|
||||
);
|
||||
@@ -381,7 +418,7 @@ EOF
|
||||
$this->initializeCatalogue($fallback);
|
||||
}
|
||||
|
||||
$fallbackCatalogue = new MessageCatalogue($fallback, $this->catalogues[$fallback]->all());
|
||||
$fallbackCatalogue = new MessageCatalogue($fallback, $this->getAllMessages($this->catalogues[$fallback]));
|
||||
foreach ($this->catalogues[$fallback]->getResources() as $resource) {
|
||||
$fallbackCatalogue->addResource($resource);
|
||||
}
|
||||
@@ -392,6 +429,10 @@ EOF
|
||||
|
||||
protected function computeFallbackLocales($locale)
|
||||
{
|
||||
if (null === $this->parentLocales) {
|
||||
$parentLocales = \json_decode(\file_get_contents(__DIR__.'/Resources/data/parents.json'), true);
|
||||
}
|
||||
|
||||
$locales = array();
|
||||
foreach ($this->fallbackLocales as $fallback) {
|
||||
if ($fallback === $locale) {
|
||||
@@ -401,8 +442,20 @@ EOF
|
||||
$locales[] = $fallback;
|
||||
}
|
||||
|
||||
if (false !== strrchr($locale, '_')) {
|
||||
array_unshift($locales, substr($locale, 0, -\strlen(strrchr($locale, '_'))));
|
||||
while ($locale) {
|
||||
$parent = $parentLocales[$locale] ?? null;
|
||||
|
||||
if (!$parent && false !== strrchr($locale, '_')) {
|
||||
$locale = substr($locale, 0, -\strlen(strrchr($locale, '_')));
|
||||
} elseif ('root' !== $parent) {
|
||||
$locale = $parent;
|
||||
} else {
|
||||
$locale = null;
|
||||
}
|
||||
|
||||
if (null !== $locale) {
|
||||
array_unshift($locales, $locale);
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($locales);
|
||||
@@ -434,4 +487,21 @@ EOF
|
||||
|
||||
return $this->configCacheFactory;
|
||||
}
|
||||
|
||||
private function getAllMessages(MessageCatalogueInterface $catalogue): array
|
||||
{
|
||||
$allMessages = array();
|
||||
|
||||
foreach ($catalogue->all() as $domain => $messages) {
|
||||
if ($intlMessages = $catalogue->all($domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
|
||||
$allMessages[$domain.MessageCatalogue::INTL_DOMAIN_SUFFIX] = $intlMessages;
|
||||
$messages = array_diff_key($messages, $intlMessages);
|
||||
}
|
||||
if ($messages) {
|
||||
$allMessages[$domain] = $messages;
|
||||
}
|
||||
}
|
||||
|
||||
return $allMessages;
|
||||
}
|
||||
}
|
||||
|
@@ -17,6 +17,8 @@ use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
* TranslatorInterface.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use Symfony\Contracts\Translation\TranslatorInterface instead
|
||||
*/
|
||||
interface TranslatorInterface
|
||||
{
|
||||
|
@@ -69,7 +69,7 @@ class ArrayConverter
|
||||
$elem = &$elem[$part];
|
||||
}
|
||||
|
||||
if (\is_array($elem) && \count($elem) > 0 && $parentOfElem) {
|
||||
if ($elem && \is_array($elem) && $parentOfElem) {
|
||||
/* Process next case:
|
||||
* 'foo.bar': 'test1'
|
||||
* 'foo': 'test2'
|
||||
|
163
vendor/symfony/translation/Util/XliffUtils.php
vendored
Normal file
163
vendor/symfony/translation/Util/XliffUtils.php
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
<?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\Translation\Util;
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\Exception\InvalidResourceException;
|
||||
|
||||
/**
|
||||
* Provides some utility methods for XLIFF translation files, such as validating
|
||||
* their contents according to the XSD schema.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class XliffUtils
|
||||
{
|
||||
/**
|
||||
* Gets xliff file version based on the root "version" attribute.
|
||||
*
|
||||
* Defaults to 1.2 for backwards compatibility.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function getVersionNumber(\DOMDocument $dom): string
|
||||
{
|
||||
/** @var \DOMNode $xliff */
|
||||
foreach ($dom->getElementsByTagName('xliff') as $xliff) {
|
||||
$version = $xliff->attributes->getNamedItem('version');
|
||||
if ($version) {
|
||||
return $version->nodeValue;
|
||||
}
|
||||
|
||||
$namespace = $xliff->attributes->getNamedItem('xmlns');
|
||||
if ($namespace) {
|
||||
if (0 !== substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34)) {
|
||||
throw new InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s"', $namespace));
|
||||
}
|
||||
|
||||
return substr($namespace, 34);
|
||||
}
|
||||
}
|
||||
|
||||
// Falls back to v1.2
|
||||
return '1.2';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and parses the given file into a DOMDocument.
|
||||
*
|
||||
* @throws InvalidResourceException
|
||||
*/
|
||||
public static function validateSchema(\DOMDocument $dom): array
|
||||
{
|
||||
$xliffVersion = static::getVersionNumber($dom);
|
||||
$internalErrors = libxml_use_internal_errors(true);
|
||||
$disableEntities = libxml_disable_entity_loader(false);
|
||||
|
||||
$isValid = @$dom->schemaValidateSource(self::getSchema($xliffVersion));
|
||||
if (!$isValid) {
|
||||
libxml_disable_entity_loader($disableEntities);
|
||||
|
||||
return self::getXmlErrors($internalErrors);
|
||||
}
|
||||
|
||||
libxml_disable_entity_loader($disableEntities);
|
||||
|
||||
$dom->normalizeDocument();
|
||||
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors($internalErrors);
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
public static function getErrorsAsString(array $xmlErrors): string
|
||||
{
|
||||
$errorsAsString = '';
|
||||
|
||||
foreach ($xmlErrors as $error) {
|
||||
$errorsAsString .= sprintf("[%s %s] %s (in %s - line %d, column %d)\n",
|
||||
LIBXML_ERR_WARNING === $error['level'] ? 'WARNING' : 'ERROR',
|
||||
$error['code'],
|
||||
$error['message'],
|
||||
$error['file'],
|
||||
$error['line'],
|
||||
$error['column']
|
||||
);
|
||||
}
|
||||
|
||||
return $errorsAsString;
|
||||
}
|
||||
|
||||
private static function getSchema(string $xliffVersion): string
|
||||
{
|
||||
if ('1.2' === $xliffVersion) {
|
||||
$schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-1.2-strict.xsd');
|
||||
$xmlUri = 'http://www.w3.org/2001/xml.xsd';
|
||||
} elseif ('2.0' === $xliffVersion) {
|
||||
$schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-2.0.xsd');
|
||||
$xmlUri = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd';
|
||||
} else {
|
||||
throw new InvalidArgumentException(sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion));
|
||||
}
|
||||
|
||||
return self::fixXmlLocation($schemaSource, $xmlUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internally changes the URI of a dependent xsd to be loaded locally.
|
||||
*/
|
||||
private static function fixXmlLocation(string $schemaSource, string $xmlUri): string
|
||||
{
|
||||
$newPath = str_replace('\\', '/', __DIR__).'/../Resources/schemas/xml.xsd';
|
||||
$parts = explode('/', $newPath);
|
||||
$locationstart = 'file:///';
|
||||
if (0 === stripos($newPath, 'phar://')) {
|
||||
$tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
|
||||
if ($tmpfile) {
|
||||
copy($newPath, $tmpfile);
|
||||
$parts = explode('/', str_replace('\\', '/', $tmpfile));
|
||||
} else {
|
||||
array_shift($parts);
|
||||
$locationstart = 'phar:///';
|
||||
}
|
||||
}
|
||||
|
||||
$drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
|
||||
$newPath = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts));
|
||||
|
||||
return str_replace($xmlUri, $newPath, $schemaSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the XML errors of the internal XML parser.
|
||||
*/
|
||||
private static function getXmlErrors(bool $internalErrors): array
|
||||
{
|
||||
$errors = array();
|
||||
foreach (libxml_get_errors() as $error) {
|
||||
$errors[] = array(
|
||||
'level' => LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
|
||||
'code' => $error->code,
|
||||
'message' => trim($error->message),
|
||||
'file' => $error->file ?: 'n/a',
|
||||
'line' => $error->line,
|
||||
'column' => $error->column,
|
||||
);
|
||||
}
|
||||
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors($internalErrors);
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
6
vendor/symfony/translation/composer.json
vendored
6
vendor/symfony/translation/composer.json
vendored
@@ -17,6 +17,7 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"symfony/contracts": "^1.0",
|
||||
"symfony/polyfill-mbstring": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -33,6 +34,9 @@
|
||||
"symfony/dependency-injection": "<3.4",
|
||||
"symfony/yaml": "<3.4"
|
||||
},
|
||||
"provide": {
|
||||
"symfony/translation-contracts-implementation": "1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/config": "",
|
||||
"symfony/yaml": "",
|
||||
@@ -47,7 +51,7 @@
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.1-dev"
|
||||
"dev-master": "4.2-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
vendor/symfony/translation/phpunit.xml.dist
vendored
2
vendor/symfony/translation/phpunit.xml.dist
vendored
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
|
Reference in New Issue
Block a user