[Translation][Extractor] Allow extracting an array of files besides extracting a directory

This commit is contained in:
Marcos Sánchez 2015-03-20 16:00:27 -03:00 committed by Fabien Potencier
parent 1a4d7d7e48
commit 9d6596c69b
11 changed files with 219 additions and 18 deletions

View File

@ -7,6 +7,7 @@ CHANGELOG
* added LogoutUrlExtension (provides `logout_url` and `logout_path`)
* added an HttpFoundation extension (provides the `absolute_url` and the `relative_path` functions)
* added AssetExtension (provides the `asset` and `asset_version` functions)
* Added possibility to extract translation messages from a file or files besides extracting from a directory
2.5.0
-----

View File

@ -0,0 +1 @@
<h1>{{ 'Hi!'|trans }}</h1>

View File

@ -83,4 +83,42 @@ class TwigExtractorTest extends \PHPUnit_Framework_TestCase
$extractor = new TwigExtractor($twig);
$extractor->extract(__DIR__.'/../Fixtures', new MessageCatalogue('en'));
}
/**
* @dataProvider resourceProvider
*/
public function testExtractWithFiles($resource)
{
$loader = new \Twig_Loader_Array(array());
$twig = new \Twig_Environment($loader, array(
'strict_variables' => true,
'debug' => true,
'cache' => false,
'autoescape' => false,
));
$twig->addExtension(new TranslationExtension($this->getMock('Symfony\Component\Translation\TranslatorInterface')));
$extractor = new TwigExtractor($twig);
$catalogue = new MessageCatalogue('en');
$extractor->extract($resource, $catalogue);
$this->assertTrue($catalogue->has('Hi!', 'messages'));
$this->assertEquals('Hi!', $catalogue->get('Hi!', 'messages'));
}
/**
* @return array
*/
public function resourceProvider()
{
$directory = __DIR__.'/../Fixtures/extractor/';
return array(
array($directory.'with_translations.html.twig'),
array(array($directory.'with_translations.html.twig')),
array(array(new \SplFileInfo($directory.'with_translations.html.twig'))),
array(new \ArrayObject(array($directory.'with_translations.html.twig'))),
array(new \ArrayObject(array(new \SplFileInfo($directory.'with_translations.html.twig')))),
);
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Bridge\Twig\Translation;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Translation\Extractor\AbstractFileExtractor;
use Symfony\Component\Translation\Extractor\ExtractorInterface;
use Symfony\Component\Translation\MessageCatalogue;
@ -21,7 +22,7 @@ use Symfony\Component\Translation\MessageCatalogue;
* @author Michel Salib <michelsalib@hotmail.com>
* @author Fabien Potencier <fabien@symfony.com>
*/
class TwigExtractor implements ExtractorInterface
class TwigExtractor extends AbstractFileExtractor implements ExtractorInterface
{
/**
* Default domain for found messages.
@ -52,11 +53,9 @@ class TwigExtractor implements ExtractorInterface
/**
* {@inheritdoc}
*/
public function extract($directory, MessageCatalogue $catalogue)
public function extract($resource, MessageCatalogue $catalogue)
{
// load any existing translation files
$finder = new Finder();
$files = $finder->files()->name('*.twig')->sortByName()->in($directory);
$files = $this->extractFiles($resource);
foreach ($files as $file) {
try {
$this->extractTemplate(file_get_contents($file->getPathname()), $catalogue);
@ -89,4 +88,26 @@ class TwigExtractor implements ExtractorInterface
$visitor->disable();
}
/**
* @param string $file
*
* @return bool
*/
protected function canBeExtracted($file)
{
return $this->isFile($file) && 'twig' === pathinfo($file, PATHINFO_EXTENSION);
}
/**
* @param string|array $directory
*
* @return array
*/
protected function extractFromDirectory($directory)
{
$finder = new Finder();
return $finder->files()->name('*.twig')->in($directory);
}
}

View File

@ -28,7 +28,7 @@
"symfony/intl": "~2.3|~3.0.0",
"symfony/routing": "~2.2|~3.0.0",
"symfony/templating": "~2.1|~3.0.0",
"symfony/translation": "~2.2|~3.0.0",
"symfony/translation": "~2.7|~3.0.0",
"symfony/yaml": "~2.0,>=2.0.5|~3.0.0",
"symfony/security": "~2.6|~3.0.0",
"symfony/stopwatch": "~2.2|~3.0.0",

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
2.7.0
-----
* Added possibility to extract translation messages from a file or files besides extracting from a directory
2.6.0
-----

View File

@ -17,7 +17,12 @@ use Symfony\Component\Translation\MessageCatalogue;
class PhpExtractorTest extends TestCase
{
public function testExtraction()
/**
* @dataProvider resourcesProvider
*
* @param array|string $resource
*/
public function testExtraction($resource)
{
// Arrange
$extractor = new PhpExtractor();
@ -25,7 +30,7 @@ class PhpExtractorTest extends TestCase
$catalogue = new MessageCatalogue('en');
// Act
$extractor->extract(__DIR__.'/../Fixtures/Resources/views/', $catalogue);
$extractor->extract($resource, $catalogue);
$expectedHeredoc = <<<EOF
heredoc key with whitespace and escaped \$\n sequences
@ -50,4 +55,28 @@ EOF;
$this->assertEquals($expectedCatalogue, $actualCatalogue);
}
public function resourcesProvider()
{
$directory = __DIR__.'/../Fixtures/Resources/views/';
$splFiles = array();
foreach (new \DirectoryIterator($directory) as $fileInfo) {
if ($fileInfo->isDot()) {
continue;
}
if ('translation.html.php' === $fileInfo->getBasename()) {
$phpFile = $fileInfo->getPathname();
}
$splFiles[] = $fileInfo->getFileInfo();
}
return array(
array($directory),
array($phpFile),
array(glob($directory.'*')),
array($splFiles),
array(new \ArrayObject(glob($directory.'*'))),
array(new \ArrayObject($splFiles)),
);
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Translation;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Translation\Extractor\AbstractFileExtractor;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Extractor\ExtractorInterface;
@ -20,7 +21,7 @@ use Symfony\Component\Translation\Extractor\ExtractorInterface;
*
* @author Michel Salib <michelsalib@hotmail.com>
*/
class PhpExtractor implements ExtractorInterface
class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface
{
const MESSAGE_TOKEN = 300;
@ -54,11 +55,9 @@ class PhpExtractor implements ExtractorInterface
/**
* {@inheritdoc}
*/
public function extract($directory, MessageCatalogue $catalog)
public function extract($resource, MessageCatalogue $catalog)
{
// load any existing translation files
$finder = new Finder();
$files = $finder->files()->name('*.php')->in($directory);
$files = $this->extractFiles($resource);
foreach ($files as $file) {
$this->parseTokens(token_get_all(file_get_contents($file)), $catalog);
}
@ -174,4 +173,28 @@ class PhpExtractor implements ExtractorInterface
}
}
}
/**
* @param string $file
*
* @throws \InvalidArgumentException
*
* @return bool
*/
protected function canBeExtracted($file)
{
return $this->isFile($file) && 'php' === pathinfo($file, PATHINFO_EXTENSION);
}
/**
* @param string|array $directory
*
* @return array
*/
protected function extractFromDirectory($directory)
{
$finder = new Finder();
return $finder->files()->name('*.php')->in($directory);
}
}

View File

@ -29,7 +29,7 @@
"symfony/security-csrf": "~2.6|~3.0.0",
"symfony/stopwatch": "~2.3|~3.0.0",
"symfony/templating": "~2.1|~3.0.0",
"symfony/translation": "~2.6|~3.0.0",
"symfony/translation": "~2.7|~3.0.0",
"doctrine/annotations": "~1.0"
},
"require-dev": {

View File

@ -0,0 +1,83 @@
<?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\Extractor;
/**
* Base class used by classes that extract translation messages from files.
*
* @author Marcos D. Sánchez <marcosdsanchez@gmail.com>
*/
abstract class AbstractFileExtractor
{
/**
* @param string|array $resource files, a file or a directory
*
* @return array
*/
protected function extractFiles($resource)
{
if (is_array($resource) || $resource instanceof \Traversable) {
$files = array();
foreach ($resource as $file) {
if ($this->canBeExtracted($file)) {
$files[] = $this->toSplFileInfo($file);
}
}
} elseif (is_file($resource)) {
$files = $this->canBeExtracted($resource) ? array($this->toSplFileInfo($resource)) : array();
} else {
$files = $this->extractFromDirectory($resource);
}
return $files;
}
/**
* @param string $file
*
* @return \SplFileInfo
*/
private function toSplFileInfo($file)
{
return ($file instanceof \SplFileInfo) ? $file : new \SplFileInfo($file);
}
/**
* @param string $file
*
* @throws \InvalidArgumentException
*
* @return bool
*/
protected function isFile($file)
{
if (!is_file($file)) {
throw new \InvalidArgumentException(sprintf('The "%s" file does not exist.', $file));
}
return true;
}
/**
* @param string $file
*
* @return bool
*/
abstract protected function canBeExtracted($file);
/**
* @param string|array $resource files, a file or a directory
*
* @return array files to be extracted
*/
abstract protected function extractFromDirectory($resource);
}

View File

@ -14,7 +14,7 @@ namespace Symfony\Component\Translation\Extractor;
use Symfony\Component\Translation\MessageCatalogue;
/**
* Extracts translation messages from a template directory to the catalogue.
* Extracts translation messages from a directory or files to the catalogue.
* New found messages are injected to the catalogue using the prefix.
*
* @author Michel Salib <michelsalib@hotmail.com>
@ -22,12 +22,12 @@ use Symfony\Component\Translation\MessageCatalogue;
interface ExtractorInterface
{
/**
* Extracts translation messages from a template directory to the catalogue.
* Extracts translation messages from files, a file or a directory to the catalogue.
*
* @param string $directory The path to look into
* @param string|array $resource files, a file or a directory
* @param MessageCatalogue $catalogue The catalogue
*/
public function extract($directory, MessageCatalogue $catalogue);
public function extract($resource, MessageCatalogue $catalogue);
/**
* Sets the prefix that should be used for new found messages.