[Translation] added some unit tests

This commit is contained in:
Fabien Potencier 2010-10-31 22:33:08 +01:00
parent ec417578ca
commit 58bd4acdd1
16 changed files with 518 additions and 39 deletions

View File

@ -59,8 +59,7 @@ class Interval
return
('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
&&
(']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
&& (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
;
}

View File

@ -94,9 +94,7 @@ class MessageCatalogue implements MessageCatalogueInterface
*/
public function setMessages($messages, $domain = 'messages')
{
if (isset($this->messages[$domain])) {
$this->messages[$domain] = array();
}
$this->messages[$domain] = array();
$this->addMessages($messages, $domain);
}
@ -118,6 +116,10 @@ class MessageCatalogue implements MessageCatalogueInterface
*/
public function addCatalogue(MessageCatalogueInterface $catalogue)
{
if ($catalogue->getLocale() !== $this->locale) {
throw new \LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s"', $catalogue->getLocale(), $this->locale));
}
foreach ($catalogue->getMessages() as $domain => $messages) {
$this->addMessages($messages, $domain);
}
@ -127,12 +129,30 @@ class MessageCatalogue implements MessageCatalogueInterface
}
}
/**
* {@inheritdoc}
*/
public function addFallbackCatalogue(MessageCatalogueInterface $catalogue)
{
foreach ($catalogue->getDomains() as $domain) {
foreach ($catalogue->getMessages($domain) as $id => $translation) {
if (false === $this->hasMessage($id, $domain)) {
$this->setMessage($id, $translation, $domain);
}
}
}
foreach ($catalogue->getResources() as $resource) {
$this->addResource($resource);
}
}
/**
* {@inheritdoc}
*/
public function getResources()
{
return array_unique($this->resources);
return array_values(array_unique($this->resources));
}
/**

View File

@ -93,10 +93,22 @@ interface MessageCatalogueInterface
/**
* Merges translations from the given Catalogue into the current one.
*
* The two catalogues must have the same locale.
*
* @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance
*/
function addCatalogue(MessageCatalogueInterface $catalogue);
/**
* Merges translations from the given Catalogue into the current one
* only when the translation does not exist.
*
* This is used to provide default translations when they do not exist for the current locale.
*
* @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance
*/
function addFallbackCatalogue(MessageCatalogueInterface $catalogue);
/**
* Returns an array of resources loaded to build this collection.
*

View File

@ -18,6 +18,7 @@ namespace Symfony\Component\Translation;
*/
class PluralizationRules
{
// @codeCoverageIgnoreStart
static protected $rules = array();
/**
@ -211,4 +212,6 @@ class PluralizationRules
self::$rules[$locale] = $rule;
}
// @codeCoverageIgnoreEnd
}

View File

@ -27,13 +27,15 @@ class FileResource implements ResourceInterface
*/
public function __construct($resource)
{
if (!file_exists($resource)) {
throw new \InvalidArgumentException(sprintf('Resource "%s" does not exist.', $resource));
}
$this->resource = realpath($resource);
}
/**
* Returns a string representation of the Resource.
*
* @return string A string representation of the Resource
* {@inheritdoc}
*/
public function __toString()
{
@ -41,9 +43,7 @@ class FileResource implements ResourceInterface
}
/**
* Returns the resource tied to this Resource.
*
* @return mixed The resource
* {@inheritdoc}
*/
public function getResource()
{
@ -51,18 +51,10 @@ class FileResource implements ResourceInterface
}
/**
* Returns true if the resource has not been updated since the given timestamp.
*
* @param timestamp $timestamp The last time the resource was loaded
*
* @return Boolean true if the resource has not been updated, false otherwise
* {@inheritdoc}
*/
public function isUptodate($timestamp)
{
if (!file_exists($this->resource)) {
return false;
}
return filemtime($this->resource) < $timestamp;
}
}

View File

@ -93,10 +93,8 @@ class Translator implements TranslatorInterface
*/
public function setFallbackLocale($locale)
{
if (null !== $this->fallbackLocale) {
// needed as the fallback locale is used to fill-in non-yet translated messages
$this->catalogues = array();
}
// needed as the fallback locale is used to fill-in non-yet translated messages
$this->catalogues = array();
$this->fallbackLocale = $locale;
}
@ -135,10 +133,6 @@ class Translator implements TranslatorInterface
protected function loadCatalogue($locale)
{
if (isset($this->catalogues[$locale])) {
return;
}
$this->catalogues[$locale] = new MessageCatalogue($locale);
if (!isset($this->resources[$locale])) {
return;
@ -162,19 +156,14 @@ class Translator implements TranslatorInterface
$fallback = $this->fallbackLocale;
}
if (!$fallback) {
return;
}
if (!isset($this->catalogues[$fallback])) {
$this->loadCatalogue($fallback);
}
foreach ($this->catalogues[$fallback]->getResources() as $resource) {
$this->catalogues[$locale]->addResource($resource);
}
foreach ($this->catalogues[$fallback]->getDomains() as $domain) {
foreach ($this->catalogues[$fallback]->getMessages($domain) as $id => $translation) {
if (false === $this->catalogues[$locale]->hasMessage($id, $domain)) {
$this->catalogues[$locale]->setMessage($id, $translation, $domain);
}
}
}
$this->catalogues[$locale]->addFallbackCatalogue($this->catalogues[$fallback]);
}
}

View File

@ -0,0 +1,61 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Component\Translation;
use Symfony\Component\Translation\IdentityTranslator;
use Symfony\Component\Translation\MessageSelector;
class IdentityTranslatorTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider getTransTests
*/
public function testTrans($expected, $id, $parameters)
{
$translator = new IdentityTranslator(new MessageSelector());
$this->assertEquals($expected, $translator->trans($id, $parameters));
}
/**
* @dataProvider getTransChoiceTests
*/
public function testTransChoice($expected, $id, $number, $parameters)
{
$translator = new IdentityTranslator(new MessageSelector());
$this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
}
// noop
public function testGetSetLocale()
{
$translator = new IdentityTranslator(new MessageSelector());
$translator->setLocale('en');
$translator->getLocale();
}
public function getTransTests()
{
return array(
array('Symfony2 is great!', 'Symfony2 is great!', array()),
array('Symfony2 is awesome!', 'Symfony2 is %what%!', array('%what%' => 'awesome')),
);
}
public function getTransChoiceTests()
{
return array(
array('There is 10 apples', '{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples', 10, array('%count%' => 10)),
);
}
}

View File

@ -0,0 +1,29 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Component\Translation\Loader;
use Symfony\Component\Translation\Loader\PhpFileLoader;
use Symfony\Component\Translation\Resource\FileResource;
class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase
{
public function testLoad()
{
$loader = new PhpFileLoader();
$resource = __DIR__.'/../fixtures/resources.php';
$catalogue = $loader->load($resource, 'en', 'domain1');
$this->assertEquals(array('foo' => 'bar'), $catalogue->getMessages('domain1'));
$this->assertEquals('en', $catalogue->getLocale());
$this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Component\Translation\Loader;
use Symfony\Component\Translation\Loader\XliffFileLoader;
use Symfony\Component\Translation\Resource\FileResource;
class XliffFileLoaderTest extends \PHPUnit_Framework_TestCase
{
public function testLoad()
{
$loader = new XliffFileLoader();
$resource = __DIR__.'/../fixtures/resources.xliff';
$catalogue = $loader->load($resource, 'en', 'domain1');
$this->assertEquals(array('foo' => 'bar'), $catalogue->getMessages('domain1'));
$this->assertEquals('en', $catalogue->getLocale());
$this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
}
/**
* @expectedException Exception
*/
public function testLoadInvalidResource()
{
$loader = new XliffFileLoader();
$catalogue = $loader->load(__DIR__.'/../fixtures/resources.php', 'en', 'domain1');
}
/**
* @expectedException Exception
*/
public function testLoadResourceDoesNotValidate()
{
$loader = new XliffFileLoader();
$catalogue = $loader->load(__DIR__.'/../fixtures/non-valid.xliff', 'en', 'domain1');
}
}

View File

@ -0,0 +1,149 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Component\Translation;
use Symfony\Component\Translation\MessageCatalogue;
class MessageCatalogueTest extends \PHPUnit_Framework_TestCase
{
public function testGetLocale()
{
$catalogue = new MessageCatalogue('en');
$this->assertEquals('en', $catalogue->getLocale());
}
public function testGetDomains()
{
$catalogue = new MessageCatalogue('en', array('domain1' => array(), 'domain2' => array()));
$this->assertEquals(array('domain1', 'domain2'), $catalogue->getDomains());
}
public function testGetMessages()
{
$catalogue = new MessageCatalogue('en', $messages = array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
$this->assertEquals(array('foo' => 'foo'), $catalogue->getMessages('domain1'));
$this->assertEquals(array(), $catalogue->getMessages('domain88'));
$this->assertEquals($messages, $catalogue->getMessages());
}
public function testHasMessage()
{
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
$this->assertTrue($catalogue->hasMessage('foo', 'domain1'));
$this->assertFalse($catalogue->hasMessage('bar', 'domain1'));
$this->assertFalse($catalogue->hasMessage('foo', 'domain88'));
}
public function testGetSetMessage()
{
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
$catalogue->setMessage('foo1', 'foo1', 'domain1');
$this->assertEquals('foo', $catalogue->getMessage('foo', 'domain1'));
$this->assertEquals('foo1', $catalogue->getMessage('foo1', 'domain1'));
}
public function testAddMessages()
{
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
$catalogue->addMessages(array('foo1' => 'foo1'), 'domain1');
$this->assertEquals('foo', $catalogue->getMessage('foo', 'domain1'));
$this->assertEquals('foo1', $catalogue->getMessage('foo1', 'domain1'));
$catalogue->addMessages(array('foo' => 'bar'), 'domain1');
$this->assertEquals('bar', $catalogue->getMessage('foo', 'domain1'));
$this->assertEquals('foo1', $catalogue->getMessage('foo1', 'domain1'));
$catalogue->addMessages(array('foo' => 'bar'), 'domain88');
$this->assertEquals('bar', $catalogue->getMessage('foo', 'domain88'));
}
public function testSetMessages()
{
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
$catalogue->setMessages($messages = array('foo1' => 'foo1'), 'domain1');
$this->assertEquals($messages, $catalogue->getMessages('domain1'));
}
public function testAddCatalogue()
{
$r = $this->getMock('Symfony\Component\Translation\Resource\ResourceInterface');
$r->expects($this->any())->method('__toString')->will($this->returnValue('r'));
$r1 = $this->getMock('Symfony\Component\Translation\Resource\ResourceInterface');
$r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));
$catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
$catalogue->addResource($r);
$catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo1' => 'foo1')));
$catalogue1->addResource($r1);
$catalogue->addCatalogue($catalogue1);
$this->assertEquals('foo', $catalogue->getMessage('foo', 'domain1'));
$this->assertEquals('foo1', $catalogue->getMessage('foo1', 'domain1'));
$this->assertEquals(array($r, $r1), $catalogue->getResources());
}
public function testAddFallbackCatalogue()
{
$r = $this->getMock('Symfony\Component\Translation\Resource\ResourceInterface');
$r->expects($this->any())->method('__toString')->will($this->returnValue('r'));
$r1 = $this->getMock('Symfony\Component\Translation\Resource\ResourceInterface');
$r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));
$catalogue = new MessageCatalogue('en_US', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
$catalogue->addResource($r);
$catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo' => 'bar', 'foo1' => 'foo1')));
$catalogue1->addResource($r1);
$catalogue->addFallbackCatalogue($catalogue1);
$this->assertEquals('foo', $catalogue->getMessage('foo', 'domain1'));
$this->assertEquals('foo1', $catalogue->getMessage('foo1', 'domain1'));
$this->assertEquals(array($r, $r1), $catalogue->getResources());
}
/**
* @expectedException LogicException
*/
public function testAddCatalogueWhenLocaleIsNotTheSameAsTheCurrentOne()
{
$catalogue = new MessageCatalogue('en');
$catalogue->addCatalogue(new MessageCatalogue('fr', array()));
}
public function testGetAddResource()
{
$catalogue = new MessageCatalogue('en');
$r = $this->getMock('Symfony\Component\Translation\Resource\ResourceInterface');
$r->expects($this->any())->method('__toString')->will($this->returnValue('r'));
$catalogue->addResource($r);
$catalogue->addResource($r);
$r1 = $this->getMock('Symfony\Component\Translation\Resource\ResourceInterface');
$r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));
$catalogue->addResource($r1);
$this->assertEquals(array($r, $r1), $catalogue->getResources());
}
}

View File

@ -0,0 +1,58 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Component\Translation;
use Symfony\Component\Translation\MessageSelector;
class MessageSelectorTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider getChooseTests
*/
public function testChoose($expected, $id, $number)
{
$selector = new MessageSelector();
$this->assertEquals($expected, $selector->choose($id, $number, 'en'));
}
/**
* @expectedException InvalidArgumentException
*/
public function testChooseWhenNoEnoughChoices()
{
$selector = new MessageSelector();
$selector->choose('foo', 10, 'en');
}
public function getChooseTests()
{
return array(
array('There is no apples', '{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples', 0),
array('There is one apple', '{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples', 1),
array('There is %count% apples', '{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples', 10),
array('There is %count% apples', 'There is one apple|There is %count% apples', 0),
array('There is one apple', 'There is one apple|There is %count% apples', 1),
array('There is %count% apples', 'There is one apple|There is %count% apples', 10),
array('There is %count% apples', 'one: There is one apple|more: There is %count% apples', 0),
array('There is one apple', 'one: There is one apple|more: There is %count% apples', 1),
array('There is %count% apples', 'one: There is one apple|more: There is %count% apples', 10),
array('There is no apples', '{0} There is no apples|one: There is one apple|more: There is %count% apples', 0),
array('There is one apple', '{0} There is no apples|one: There is one apple|more: There is %count% apples', 1),
array('There is %count% apples', '{0} There is no apples|one: There is one apple|more: There is %count% apples', 10),
);
}
}

View File

@ -0,0 +1,48 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Component\Translation\Resource;
use Symfony\Component\Translation\Resource\FileResource;
class FileResourceTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testConstructor()
{
$resource = new FileResource(__DIR__.'/../fixtures/foobar');
}
public function testMagicToString()
{
$resource = new FileResource(__DIR__.'/../fixtures/resources.php');
$this->assertEquals(realpath(__DIR__.'/../fixtures/resources.php'), (string) $resource);
}
public function testGetResource()
{
$resource = new FileResource(__DIR__.'/../fixtures/resources.php');
$this->assertEquals(realpath(__DIR__.'/../fixtures/resources.php'), $resource->getResource());
}
public function testIsUptodate()
{
$r = __DIR__.'/../fixtures/resources.php';
$resource = new FileResource($r);
$this->assertFalse($resource->isUptodate(filemtime($r) - 100));
$this->assertTrue($resource->isUptodate(filemtime($r) + 100));
}
}

View File

@ -17,6 +17,51 @@ use Symfony\Component\Translation\Loader\ArrayLoader;
class TranslatorTest extends \PHPUnit_Framework_TestCase
{
public function testSetGetLocale()
{
$translator = new Translator('en', new MessageSelector());
$this->assertEquals('en', $translator->getLocale());
$translator->setLocale('fr');
$this->assertEquals('fr', $translator->getLocale());
}
public function testSetFallbackLocale()
{
$translator = new Translator('en', new MessageSelector());
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
$translator->addResource('array', array('bar' => 'foobar'), 'fr');
// force catalogue loading
$translator->trans('bar');
$translator->setFallbackLocale('fr');
$this->assertEquals('foobar', $translator->trans('bar'));
}
public function testTransWithFallbackLocale()
{
$translator = new Translator('en_US', new MessageSelector());
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('foo' => 'foofoo'), 'en_US');
$translator->addResource('array', array('bar' => 'foobar'), 'en');
$this->assertEquals('foobar', $translator->trans('bar'));
}
/**
* @expectedException RuntimeException
*/
public function testWhenAResourceHasNoRegisteredLoader()
{
$translator = new Translator('en', new MessageSelector());
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
$translator->trans('foo');
}
/**
* @dataProvider getTransTests
*/

View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit>
<source>foo</source>
<target>bar</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -0,0 +1,5 @@
<?php
return array(
'foo' => 'bar',
);

View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="1">
<source>foo</source>
<target>bar</target>
</trans-unit>
</body>
</file>
</xliff>