feature#8534 [Translation] Added support for JSON format (both loader and dumper). (singles)
This PR was merged into the master branch.
Discussion
----------
[Translation] Added support for JSON format (both loader and dumper).
Based on `IniFileLoader\Dumper`.
Q | A
--- | ---
Bug fix? |no
New feature? | yes
BC breaks?| no
Deprecations? |no
Tests pass? | yes
Fixed tickets | -
License | MIT
Doc | this component don't have docs
Commits
-------
fcef021
[Translation] Added support for JSON format (both loader and dumper).
This commit is contained in:
commit
9988475881
@ -18,6 +18,7 @@
|
|||||||
<parameter key="translation.loader.res.class">Symfony\Component\Translation\Loader\IcuResFileLoader</parameter>
|
<parameter key="translation.loader.res.class">Symfony\Component\Translation\Loader\IcuResFileLoader</parameter>
|
||||||
<parameter key="translation.loader.dat.class">Symfony\Component\Translation\Loader\IcuDatFileLoader</parameter>
|
<parameter key="translation.loader.dat.class">Symfony\Component\Translation\Loader\IcuDatFileLoader</parameter>
|
||||||
<parameter key="translation.loader.ini.class">Symfony\Component\Translation\Loader\IniFileLoader</parameter>
|
<parameter key="translation.loader.ini.class">Symfony\Component\Translation\Loader\IniFileLoader</parameter>
|
||||||
|
<parameter key="translation.loader.json.class">Symfony\Component\Translation\Loader\JsonFileLoader</parameter>
|
||||||
<parameter key="translation.dumper.php.class">Symfony\Component\Translation\Dumper\PhpFileDumper</parameter>
|
<parameter key="translation.dumper.php.class">Symfony\Component\Translation\Dumper\PhpFileDumper</parameter>
|
||||||
<parameter key="translation.dumper.xliff.class">Symfony\Component\Translation\Dumper\XliffFileDumper</parameter>
|
<parameter key="translation.dumper.xliff.class">Symfony\Component\Translation\Dumper\XliffFileDumper</parameter>
|
||||||
<parameter key="translation.dumper.po.class">Symfony\Component\Translation\Dumper\PoFileDumper</parameter>
|
<parameter key="translation.dumper.po.class">Symfony\Component\Translation\Dumper\PoFileDumper</parameter>
|
||||||
@ -26,6 +27,7 @@
|
|||||||
<parameter key="translation.dumper.qt.class">Symfony\Component\Translation\Dumper\QtFileDumper</parameter>
|
<parameter key="translation.dumper.qt.class">Symfony\Component\Translation\Dumper\QtFileDumper</parameter>
|
||||||
<parameter key="translation.dumper.csv.class">Symfony\Component\Translation\Dumper\CsvFileDumper</parameter>
|
<parameter key="translation.dumper.csv.class">Symfony\Component\Translation\Dumper\CsvFileDumper</parameter>
|
||||||
<parameter key="translation.dumper.ini.class">Symfony\Component\Translation\Dumper\IniFileDumper</parameter>
|
<parameter key="translation.dumper.ini.class">Symfony\Component\Translation\Dumper\IniFileDumper</parameter>
|
||||||
|
<parameter key="translation.dumper.json.class">Symfony\Component\Translation\Dumper\JsonFileDumper</parameter>
|
||||||
<parameter key="translation.dumper.res.class">Symfony\Component\Translation\Dumper\IcuResFileDumper</parameter>
|
<parameter key="translation.dumper.res.class">Symfony\Component\Translation\Dumper\IcuResFileDumper</parameter>
|
||||||
<parameter key="translation.extractor.php.class">Symfony\Bundle\FrameworkBundle\Translation\PhpExtractor</parameter>
|
<parameter key="translation.extractor.php.class">Symfony\Bundle\FrameworkBundle\Translation\PhpExtractor</parameter>
|
||||||
<parameter key="translation.loader.class">Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader</parameter>
|
<parameter key="translation.loader.class">Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader</parameter>
|
||||||
@ -90,6 +92,10 @@
|
|||||||
<tag name="translation.loader" alias="ini" />
|
<tag name="translation.loader" alias="ini" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service id="translation.loader.json" class="%translation.loader.json.class%">
|
||||||
|
<tag name="translation.loader" alias="json" />
|
||||||
|
</service>
|
||||||
|
|
||||||
<service id="translation.dumper.php" class="%translation.dumper.php.class%">
|
<service id="translation.dumper.php" class="%translation.dumper.php.class%">
|
||||||
<tag name="translation.dumper" alias="php" />
|
<tag name="translation.dumper" alias="php" />
|
||||||
</service>
|
</service>
|
||||||
@ -122,6 +128,10 @@
|
|||||||
<tag name="translation.dumper" alias="ini" />
|
<tag name="translation.dumper" alias="ini" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service id="translation.dumper.json" class="%translation.dumper.json.class%">
|
||||||
|
<tag name="translation.dumper" alias="json" />
|
||||||
|
</service>
|
||||||
|
|
||||||
<service id="translation.dumper.res" class="%translation.dumper.res.class%">
|
<service id="translation.dumper.res" class="%translation.dumper.res.class%">
|
||||||
<tag name="translation.dumper" alias="res" />
|
<tag name="translation.dumper" alias="res" />
|
||||||
</service>
|
</service>
|
||||||
|
42
src/Symfony/Component/Translation/Dumper/JsonFileDumper.php
Normal file
42
src/Symfony/Component/Translation/Dumper/JsonFileDumper.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Translation\Dumper;
|
||||||
|
|
||||||
|
use Symfony\Component\Translation\MessageCatalogue;
|
||||||
|
|
||||||
|
if (!defined('JSON_PRETTY_PRINT')) {
|
||||||
|
define('JSON_PRETTY_PRINT', 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JsonFileDumper generates an json formatted string representation of a message catalogue.
|
||||||
|
*
|
||||||
|
* @author singles
|
||||||
|
*/
|
||||||
|
class JsonFileDumper extends FileDumper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function format(MessageCatalogue $messages, $domain = 'messages')
|
||||||
|
{
|
||||||
|
return json_encode($messages->all($domain), JSON_PRETTY_PRINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
protected function getExtension()
|
||||||
|
{
|
||||||
|
return 'json';
|
||||||
|
}
|
||||||
|
}
|
87
src/Symfony/Component/Translation/Loader/JsonFileLoader.php
Normal file
87
src/Symfony/Component/Translation/Loader/JsonFileLoader.php
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?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\Loader;
|
||||||
|
|
||||||
|
use Symfony\Component\Translation\Exception\InvalidResourceException;
|
||||||
|
use Symfony\Component\Translation\Exception\NotFoundResourceException;
|
||||||
|
use Symfony\Component\Config\Resource\FileResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JsonFileLoader loads translations from an json file.
|
||||||
|
*
|
||||||
|
* @author singles
|
||||||
|
*/
|
||||||
|
class JsonFileLoader extends ArrayLoader implements LoaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function load($resource, $locale, $domain = 'messages')
|
||||||
|
{
|
||||||
|
if (!stream_is_local($resource)) {
|
||||||
|
throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($resource)) {
|
||||||
|
throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
$messages = json_decode(file_get_contents($resource), true);
|
||||||
|
|
||||||
|
if (($errorCode = json_last_error()) > 0) {
|
||||||
|
$message = $this->getJSONErrorMessage($errorCode);
|
||||||
|
throw new InvalidResourceException(sprintf('Error parsing JSON - %s', $message));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($messages === null) {
|
||||||
|
$messages = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$catalogue = parent::load($messages, $locale, $domain);
|
||||||
|
$catalogue->addResource(new FileResource($resource));
|
||||||
|
|
||||||
|
return $catalogue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates JSON_ERROR_* constant into meaningful message
|
||||||
|
*
|
||||||
|
* @param integer $errorCode Error code returned by json_last_error() call
|
||||||
|
* @return string Message string
|
||||||
|
*/
|
||||||
|
private function getJSONErrorMessage($errorCode)
|
||||||
|
{
|
||||||
|
$errorMsg = null;
|
||||||
|
switch ($errorCode) {
|
||||||
|
case JSON_ERROR_DEPTH:
|
||||||
|
$errorMsg = 'Maximum stack depth exceeded';
|
||||||
|
break;
|
||||||
|
case JSON_ERROR_STATE_MISMATCH:
|
||||||
|
$errorMsg = 'Underflow or the modes mismatch';
|
||||||
|
break;
|
||||||
|
case JSON_ERROR_CTRL_CHAR:
|
||||||
|
$errorMsg = 'Unexpected control character found';
|
||||||
|
break;
|
||||||
|
case JSON_ERROR_SYNTAX:
|
||||||
|
$errorMsg = 'Syntax error, malformed JSON';
|
||||||
|
break;
|
||||||
|
case JSON_ERROR_UTF8:
|
||||||
|
$errorMsg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$errorMsg = 'Unknown error';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errorMsg;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
<?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\Dumper;
|
||||||
|
|
||||||
|
use Symfony\Component\Translation\MessageCatalogue;
|
||||||
|
use Symfony\Component\Translation\Dumper\JsonFileDumper;
|
||||||
|
|
||||||
|
class JsonFileDumperTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testDump()
|
||||||
|
{
|
||||||
|
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
|
||||||
|
$this->markTestIncomplete('PHP below 5.4 doesn\'t support JSON pretty printing');
|
||||||
|
}
|
||||||
|
|
||||||
|
$catalogue = new MessageCatalogue('en');
|
||||||
|
$catalogue->add(array('foo' => 'bar'));
|
||||||
|
|
||||||
|
$tempDir = sys_get_temp_dir();
|
||||||
|
$dumper = new JsonFileDumper();
|
||||||
|
$dumper->dump($catalogue, array('path' => $tempDir));
|
||||||
|
|
||||||
|
$this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.json'), file_get_contents($tempDir.'/messages.en.json'));
|
||||||
|
|
||||||
|
unlink($tempDir.'/messages.en.json');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
<?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\Loader;
|
||||||
|
|
||||||
|
use Symfony\Component\Translation\Loader\JsonFileLoader;
|
||||||
|
use Symfony\Component\Config\Resource\FileResource;
|
||||||
|
|
||||||
|
class JsonFileLoaderTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
if (!class_exists('Symfony\Component\Config\Loader\Loader')) {
|
||||||
|
$this->markTestSkipped('The "Config" component is not available');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoad()
|
||||||
|
{
|
||||||
|
$loader = new JsonFileLoader();
|
||||||
|
$resource = __DIR__.'/../fixtures/resources.json';
|
||||||
|
$catalogue = $loader->load($resource, 'en', 'domain1');
|
||||||
|
|
||||||
|
$this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
|
||||||
|
$this->assertEquals('en', $catalogue->getLocale());
|
||||||
|
$this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadDoesNothingIfEmpty()
|
||||||
|
{
|
||||||
|
$loader = new JsonFileLoader();
|
||||||
|
$resource = __DIR__.'/../fixtures/empty.json';
|
||||||
|
$catalogue = $loader->load($resource, 'en', 'domain1');
|
||||||
|
|
||||||
|
$this->assertEquals(array(), $catalogue->all('domain1'));
|
||||||
|
$this->assertEquals('en', $catalogue->getLocale());
|
||||||
|
$this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
|
||||||
|
*/
|
||||||
|
public function testLoadNonExistingResource()
|
||||||
|
{
|
||||||
|
$loader = new JsonFileLoader();
|
||||||
|
$resource = __DIR__.'/../fixtures/non-existing.json';
|
||||||
|
$loader->load($resource, 'en', 'domain1');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
|
||||||
|
* @expectedExceptionMessage Error parsing JSON - Syntax error, malformed JSON
|
||||||
|
*/
|
||||||
|
public function testParseException()
|
||||||
|
{
|
||||||
|
$loader = new JsonFileLoader();
|
||||||
|
$resource = __DIR__.'/../fixtures/malformed.json';
|
||||||
|
$loader->load($resource, 'en', 'domain1');
|
||||||
|
}
|
||||||
|
}
|
@ -199,6 +199,7 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase
|
|||||||
array('ts', 'QtFileLoader'),
|
array('ts', 'QtFileLoader'),
|
||||||
array('xlf', 'XliffFileLoader'),
|
array('xlf', 'XliffFileLoader'),
|
||||||
array('yml', 'YamlFileLoader'),
|
array('yml', 'YamlFileLoader'),
|
||||||
|
array('json', 'JsonFileLoader'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
src/Symfony/Component/Translation/Tests/fixtures/empty.json
vendored
Normal file
0
src/Symfony/Component/Translation/Tests/fixtures/empty.json
vendored
Normal file
3
src/Symfony/Component/Translation/Tests/fixtures/malformed.json
vendored
Normal file
3
src/Symfony/Component/Translation/Tests/fixtures/malformed.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"foo": "bar" "
|
||||||
|
}
|
3
src/Symfony/Component/Translation/Tests/fixtures/resources.json
vendored
Normal file
3
src/Symfony/Component/Translation/Tests/fixtures/resources.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"foo": "bar"
|
||||||
|
}
|
Reference in New Issue
Block a user