Merge branch '2.8' into 3.0

* 2.8:
  [DependencyInjection] fix dumped YAML snytax
  Remove InputOption::VALUE_REQUIRED mode from $default parameter description as InputOption::setDefault() throws an exception only when called in InputOption::VALUE_NONE mode. In practice the $default value could still be accessed in InputOption::VALUE_REQUIRED mode in case InputOption was never set but accessed from InputDefinition::getOption() method
  [Form] Fixed violation mapping if multiple forms are using the same (or part of the same) property path
  fix FQCN in tests added by #17694
  Fix locale and written standard inconsistencies for Norwegian translations
  [Form] [Validator] Fix locale inconsistencies in Norwegian translations
  [TwigBridge] Symfony 3.1 forward compatibility
  fixed CS
  [DependencyInjection] fixed exceptions thrown by get method of ContainerBuilder
  [Yaml] properly parse lists in object maps
  [FrameworkBundle] Remove unused private method.
  [Form] remove useless code in ResizeFormListener
  [Config] Fix EnumNodeDefinition to allow building enum nodes with one element
  fix choice_value option in EntityType and add some tests
This commit is contained in:
Fabien Potencier 2016-02-16 07:11:42 +01:00
commit 2128d52cb8
24 changed files with 483 additions and 369 deletions

View File

@ -146,7 +146,7 @@ class DoctrineChoiceLoader implements ChoiceLoaderInterface
// Optimize performance in case we have an object loader and // Optimize performance in case we have an object loader and
// a single-field identifier // a single-field identifier
if (!$this->choiceList && $this->objectLoader && $this->idReader->isSingleId()) { if (null === $value && !$this->choiceList && $this->objectLoader && $this->idReader->isSingleId()) {
$unorderedObjects = $this->objectLoader->getEntitiesByIds($this->idReader->getIdField(), $values); $unorderedObjects = $this->objectLoader->getEntitiesByIds($this->idReader->getIdField(), $values);
$objectsById = array(); $objectsById = array();
$objects = array(); $objects = array();

View File

@ -753,6 +753,55 @@ class EntityTypeTest extends TypeTestCase
$this->assertSame('2', $field->getViewData()); $this->assertSame('2', $field->getViewData());
} }
public function testOverrideChoicesValues()
{
$entity1 = new SingleIntIdEntity(1, 'Foo');
$entity2 = new SingleIntIdEntity(2, 'Bar');
$this->persist(array($entity1, $entity2));
$field = $this->factory->createNamed('name', 'Symfony\Bridge\Doctrine\Form\Type\EntityType', null, array(
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'choice_label' => 'name',
'choice_value' => 'name',
));
$field->submit('Bar');
$this->assertEquals(array('Foo' => new ChoiceView($entity1, 'Foo', 'Foo'), 'Bar' => new ChoiceView($entity2, 'Bar', 'Bar')), $field->createView()->vars['choices']);
$this->assertTrue($field->isSynchronized(), 'Field should be synchronized.');
$this->assertSame($entity2, $field->getData(), 'Entity should be loaded by custom value.');
$this->assertSame('Bar', $field->getViewData());
}
public function testOverrideChoicesValuesWithCallable()
{
$entity1 = new GroupableEntity(1, 'Foo', 'BazGroup');
$entity2 = new GroupableEntity(2, 'Bar', 'BooGroup');
$this->persist(array($entity1, $entity2));
$field = $this->factory->createNamed('name', 'Symfony\Bridge\Doctrine\Form\Type\EntityType', null, array(
'em' => 'default',
'class' => self::ITEM_GROUP_CLASS,
'choice_label' => 'name',
'choice_value' => function (GroupableEntity $entity) {
return $entity->groupName.'/'.$entity->name;
},
));
$field->submit('BooGroup/Bar');
$this->assertEquals(array(
'BazGroup/Foo' => new ChoiceView($entity1, 'BazGroup/Foo', 'Foo'),
'BooGroup/Bar' => new ChoiceView($entity2, 'BooGroup/Bar', 'Bar'),
), $field->createView()->vars['choices']);
$this->assertTrue($field->isSynchronized(), 'Field should be synchronized.');
$this->assertSame($entity2, $field->getData(), 'Entity should be loaded by custom value.');
$this->assertSame('BooGroup/Bar', $field->getViewData());
}
public function testGroupByChoices() public function testGroupByChoices()
{ {
$item1 = new GroupableEntity(1, 'Foo', 'Group1'); $item1 = new GroupableEntity(1, 'Foo', 'Group1');

View File

@ -12,6 +12,7 @@
namespace Symfony\Bridge\Twig\Extension; namespace Symfony\Bridge\Twig\Extension;
use Symfony\Component\Yaml\Dumper as YamlDumper; use Symfony\Component\Yaml\Dumper as YamlDumper;
use Symfony\Component\Yaml\Yaml;
/** /**
* Provides integration of the Yaml component with Twig. * Provides integration of the Yaml component with Twig.
@ -40,7 +41,7 @@ class YamlExtension extends \Twig_Extension
} }
if (defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) { if (defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) {
$dumpObjects = (int) $dumpObjects; return $dumper->dump($input, $inline, 0, is_bool($dumpObjects) ? Yaml::DUMP_OBJECT : 0);
} }
return $dumper->dump($input, $inline, 0, false, $dumpObjects); return $dumper->dump($input, $inline, 0, false, $dumpObjects);

View File

@ -411,17 +411,6 @@ class TextDescriptor extends Descriptor
return trim($configAsString); return trim($configAsString);
} }
/**
* @param string $section
* @param string $message
*
* @return string
*/
private function formatSection($section, $message)
{
return sprintf('<info>[%s]</info> %s', $section, $message);
}
/** /**
* @param callable $callable * @param callable $callable
* *

View File

@ -31,8 +31,8 @@ class EnumNodeDefinition extends ScalarNodeDefinition
{ {
$values = array_unique($values); $values = array_unique($values);
if (count($values) <= 1) { if (empty($values)) {
throw new \InvalidArgumentException('->values() must be called with at least two distinct values.'); throw new \InvalidArgumentException('->values() must be called with at least one value.');
} }
$this->values = $values; $this->values = $values;

View File

@ -15,14 +15,22 @@ use Symfony\Component\Config\Definition\Builder\EnumNodeDefinition;
class EnumNodeDefinitionTest extends \PHPUnit_Framework_TestCase class EnumNodeDefinitionTest extends \PHPUnit_Framework_TestCase
{ {
/** public function testWithOneValue()
* @expectedException \InvalidArgumentException {
* @expectedExceptionMessage ->values() must be called with at least two distinct values. $def = new EnumNodeDefinition('foo');
*/ $def->values(array('foo'));
public function testNoDistinctValues()
$node = $def->getNode();
$this->assertEquals(array('foo'), $node->getValues());
}
public function testWithOneDistinctValue()
{ {
$def = new EnumNodeDefinition('foo'); $def = new EnumNodeDefinition('foo');
$def->values(array('foo', 'foo')); $def->values(array('foo', 'foo'));
$node = $def->getNode();
$this->assertEquals(array('foo'), $node->getValues());
} }
/** /**
@ -35,6 +43,16 @@ class EnumNodeDefinitionTest extends \PHPUnit_Framework_TestCase
$def->getNode(); $def->getNode();
} }
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage ->values() must be called with at least one value.
*/
public function testWithNoValues()
{
$def = new EnumNodeDefinition('foo');
$def->values(array());
}
public function testGetNode() public function testGetNode()
{ {
$def = new EnumNodeDefinition('foo'); $def = new EnumNodeDefinition('foo');

View File

@ -383,7 +383,7 @@ class Command
* @param string $shortcut The shortcut (can be null) * @param string $shortcut The shortcut (can be null)
* @param int $mode The option mode: One of the InputOption::VALUE_* constants * @param int $mode The option mode: One of the InputOption::VALUE_* constants
* @param string $description A description text * @param string $description A description text
* @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE) * @param mixed $default The default value (must be null for InputOption::VALUE_NONE)
* *
* @return Command The current instance * @return Command The current instance
*/ */

View File

@ -39,7 +39,7 @@ class InputOption
* @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts * @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
* @param int $mode The option mode: One of the VALUE_* constants * @param int $mode The option mode: One of the VALUE_* constants
* @param string $description A description text * @param string $description A description text
* @param mixed $default The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE) * @param mixed $default The default value (must be null for self::VALUE_NONE)
* *
* @throws InvalidArgumentException If option mode is invalid or incompatible * @throws InvalidArgumentException If option mode is invalid or incompatible
*/ */

View File

@ -18,6 +18,8 @@ use Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Config\Resource\ResourceInterface;
@ -398,8 +400,9 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
* *
* @return object The associated service * @return object The associated service
* *
* @throws InvalidArgumentException when no definitions are available * @throws InvalidArgumentException when no definitions are available
* @throws LogicException when a circular dependency is detected * @throws ServiceCircularReferenceException When a circular reference is detected
* @throws ServiceNotFoundException When the service is not defined
* @throws \Exception * @throws \Exception
* *
* @see Reference * @see Reference
@ -418,7 +421,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
try { try {
$definition = $this->getDefinition($id); $definition = $this->getDefinition($id);
} catch (InvalidArgumentException $e) { } catch (ServiceNotFoundException $e) {
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
return; return;
} }
@ -758,14 +761,14 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
* *
* @return Definition A Definition instance * @return Definition A Definition instance
* *
* @throws InvalidArgumentException if the service definition does not exist * @throws ServiceNotFoundException if the service definition does not exist
*/ */
public function getDefinition($id) public function getDefinition($id)
{ {
$id = strtolower($id); $id = strtolower($id);
if (!array_key_exists($id, $this->definitions)) { if (!array_key_exists($id, $this->definitions)) {
throw new InvalidArgumentException(sprintf('The service definition "%s" does not exist.', $id)); throw new ServiceNotFoundException($id);
} }
return $this->definitions[$id]; return $this->definitions[$id];
@ -780,7 +783,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
* *
* @return Definition A Definition instance * @return Definition A Definition instance
* *
* @throws InvalidArgumentException if the service definition does not exist * @throws ServiceNotFoundException if the service definition does not exist
*/ */
public function findDefinition($id) public function findDefinition($id)
{ {

View File

@ -65,7 +65,7 @@ class YamlDumper extends Dumper
$class = substr($class, 1); $class = substr($class, 1);
} }
$code .= sprintf(" class: %s\n", $class); $code .= sprintf(" class: %s\n", $this->dumper->dump($class));
} }
if (!$definition->isPublic()) { if (!$definition->isPublic()) {

View File

@ -20,6 +20,9 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader; use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@ -49,9 +52,9 @@ class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
try { try {
$builder->getDefinition('baz'); $builder->getDefinition('baz');
$this->fail('->getDefinition() throws an InvalidArgumentException if the service definition does not exist'); $this->fail('->getDefinition() throws a ServiceNotFoundException if the service definition does not exist');
} catch (\InvalidArgumentException $e) { } catch (ServiceNotFoundException $e) {
$this->assertEquals('The service definition "baz" does not exist.', $e->getMessage(), '->getDefinition() throws an InvalidArgumentException if the service definition does not exist'); $this->assertEquals('You have requested a non-existent service "baz".', $e->getMessage(), '->getDefinition() throws a ServiceNotFoundException if the service definition does not exist');
} }
} }
@ -101,9 +104,9 @@ class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
$builder = new ContainerBuilder(); $builder = new ContainerBuilder();
try { try {
$builder->get('foo'); $builder->get('foo');
$this->fail('->get() throws an InvalidArgumentException if the service does not exist'); $this->fail('->get() throws a ServiceNotFoundException if the service does not exist');
} catch (\InvalidArgumentException $e) { } catch (ServiceNotFoundException $e) {
$this->assertEquals('The service definition "foo" does not exist.', $e->getMessage(), '->get() throws an InvalidArgumentException if the service does not exist'); $this->assertEquals('You have requested a non-existent service "foo".', $e->getMessage(), '->get() throws a ServiceNotFoundException if the service does not exist');
} }
$this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service does not exist and NULL_ON_INVALID_REFERENCE is passed as a second argument'); $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service does not exist and NULL_ON_INVALID_REFERENCE is passed as a second argument');

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Dumper;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\YamlDumper; use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
use Symfony\Component\Yaml\Yaml;
class YamlDumperTest extends \PHPUnit_Framework_TestCase class YamlDumperTest extends \PHPUnit_Framework_TestCase
{ {
@ -27,24 +28,21 @@ class YamlDumperTest extends \PHPUnit_Framework_TestCase
{ {
$dumper = new YamlDumper($container = new ContainerBuilder()); $dumper = new YamlDumper($container = new ContainerBuilder());
$this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services1.yml', $dumper->dump(), '->dump() dumps an empty container as an empty YAML file'); $this->assertEqualYamlStructure(self::$fixturesPath.'/yaml/services1.yml', $dumper->dump(), '->dump() dumps an empty container as an empty YAML file');
$container = new ContainerBuilder();
$dumper = new YamlDumper($container);
} }
public function testAddParameters() public function testAddParameters()
{ {
$container = include self::$fixturesPath.'/containers/container8.php'; $container = include self::$fixturesPath.'/containers/container8.php';
$dumper = new YamlDumper($container); $dumper = new YamlDumper($container);
$this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services8.yml', $dumper->dump(), '->dump() dumps parameters'); $this->assertEqualYamlStructure(self::$fixturesPath.'/yaml/services8.yml', $dumper->dump(), '->dump() dumps parameters');
} }
public function testAddService() public function testAddService()
{ {
$container = include self::$fixturesPath.'/containers/container9.php'; $container = include self::$fixturesPath.'/containers/container9.php';
$dumper = new YamlDumper($container); $dumper = new YamlDumper($container);
$this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/yaml/services9.yml')), $dumper->dump(), '->dump() dumps services'); $this->assertEqualYamlStructure(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/yaml/services9.yml')), $dumper->dump(), '->dump() dumps services');
$dumper = new YamlDumper($container = new ContainerBuilder()); $dumper = new YamlDumper($container = new ContainerBuilder());
$container->register('foo', 'FooClass')->addArgument(new \stdClass()); $container->register('foo', 'FooClass')->addArgument(new \stdClass());
@ -63,4 +61,9 @@ class YamlDumperTest extends \PHPUnit_Framework_TestCase
$dumper = new YamlDumper($container); $dumper = new YamlDumper($container);
$this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services24.yml', $dumper->dump()); $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services24.yml', $dumper->dump());
} }
private function assertEqualYamlStructure($yaml, $expected, $message = '')
{
$this->assertEquals(Yaml::parse($expected), Yaml::parse($yaml), $message);
}
} }

View File

@ -6,4 +6,4 @@ services:
class: BAR class: BAR
project: project:
test: %project.parameter.foo% test: '%project.parameter.foo%'

View File

@ -2,7 +2,7 @@ services:
foo: { class: FooClass } foo: { class: FooClass }
baz: { class: BazClass } baz: { class: BazClass }
not_shared: { class: FooClass, shared: false } not_shared: { class: FooClass, shared: false }
file: { class: FooClass, file: %path%/foo.php } file: { class: FooClass, file: '%path%/foo.php' }
arguments: { class: FooClass, arguments: [foo, '@foo', [true, false]] } arguments: { class: FooClass, arguments: [foo, '@foo', [true, false]] }
configurator1: { class: FooClass, configurator: sc_configure } configurator1: { class: FooClass, configurator: sc_configure }
configurator2: { class: FooClass, configurator: ['@baz', configure] } configurator2: { class: FooClass, configurator: ['@baz', configure] }

View File

@ -18,7 +18,7 @@ services:
factory: [Bar\FooClass, getInstance] factory: [Bar\FooClass, getInstance]
configurator: sc_configure configurator: sc_configure
foo.baz: foo.baz:
class: %baz_class% class: '%baz_class%'
factory: ['%baz_class%', getInstance] factory: ['%baz_class%', getInstance]
configurator: ['%baz_class%', configureStatic1] configurator: ['%baz_class%', configureStatic1]
bar: bar:
@ -26,11 +26,11 @@ services:
arguments: [foo, '@foo.baz', '%foo_bar%'] arguments: [foo, '@foo.baz', '%foo_bar%']
configurator: ['@foo.baz', configure] configurator: ['@foo.baz', configure]
foo_bar: foo_bar:
class: %foo_class% class: '%foo_class%'
shared: false shared: false
method_call1: method_call1:
class: Bar\FooClass class: Bar\FooClass
file: %path%foo.php file: '%path%foo.php'
calls: calls:
- [setBar, ['@foo']] - [setBar, ['@foo']]
- [setBar, ['@?foo2']] - [setBar, ['@?foo2']]

View File

@ -102,10 +102,6 @@ class ResizeFormListener implements EventSubscriberInterface
$form = $event->getForm(); $form = $event->getForm();
$data = $event->getData(); $data = $event->getData();
if (null === $data || '' === $data) {
$data = array();
}
if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
$data = array(); $data = array();
} }

View File

@ -148,12 +148,9 @@ class ViolationMapper implements ViolationMapperInterface
*/ */
private function matchChild(FormInterface $form, PropertyPathIteratorInterface $it) private function matchChild(FormInterface $form, PropertyPathIteratorInterface $it)
{ {
// Remember at what property path underneath "data" $target = null;
// we are looking. Check if there is a child with that
// path, otherwise increase path by one more piece
$chunk = ''; $chunk = '';
$foundChild = null; $foundAtIndex = null;
$foundAtIndex = 0;
// Construct mapping rules for the given form // Construct mapping rules for the given form
$rules = array(); $rules = array();
@ -165,17 +162,11 @@ class ViolationMapper implements ViolationMapperInterface
} }
} }
// Skip forms inheriting their parent data when iterating the children $children = iterator_to_array(new \RecursiveIteratorIterator(
$childIterator = new \RecursiveIteratorIterator(
new InheritDataAwareIterator($form) new InheritDataAwareIterator($form)
); ));
// Make the path longer until we find a matching child
while (true) {
if (!$it->valid()) {
return;
}
while ($it->valid()) {
if ($it->isIndex()) { if ($it->isIndex()) {
$chunk .= '['.$it->current().']'; $chunk .= '['.$it->current().']';
} else { } else {
@ -197,33 +188,27 @@ class ViolationMapper implements ViolationMapperInterface
} }
} }
// Test children unless we already found one /** @var FormInterface $child */
if (null === $foundChild) { foreach ($children as $key => $child) {
foreach ($childIterator as $child) { $childPath = (string) $child->getPropertyPath();
/* @var FormInterface $child */ if ($childPath === $chunk) {
$childPath = (string) $child->getPropertyPath(); $target = $child;
$foundAtIndex = $it->key();
// Child found, mark as return value } elseif (0 === strpos($childPath, $chunk)) {
if ($chunk === $childPath) { continue;
$foundChild = $child;
$foundAtIndex = $it->key();
}
} }
unset($children[$key]);
} }
// Add element to the chunk
$it->next(); $it->next();
// If we reached the end of the path or if there are no
// more matching mapping rules, return the found child
if (null !== $foundChild && (!$it->valid() || count($rules) === 0)) {
// Reset index in case we tried to find mapping
// rules further down the path
$it->seek($foundAtIndex);
return $foundChild;
}
} }
if (null !== $foundAtIndex) {
$it->seek($foundAtIndex);
}
return $target;
} }
/** /**

View File

@ -1539,4 +1539,25 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array($this->getFormError($violation, $grandChild)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); $this->assertEquals(array($this->getFormError($violation, $grandChild)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none');
} }
} }
public function testBacktrackIfSeveralSubFormsWithSamePropertyPath()
{
$violation = $this->getConstraintViolation('data.address[street]');
$parent = $this->getForm('parent');
$child1 = $this->getForm('subform1', 'address');
$child2 = $this->getForm('subform2', 'address');
$grandChild = $this->getForm('street');
$parent->add($child1);
$parent->add($child2);
$child2->add($grandChild);
$this->mapper->mapViolation($violation, $parent);
// The error occurred on the child of the second form with the same path
$this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
$this->assertCount(0, $child1->getErrors(), $child1->getName().' should not have an error, but has one');
$this->assertCount(0, $child2->getErrors(), $child2->getName().' should not have an error, but has one');
$this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChild->getName().' should have an error, but has none');
}
} }

View File

@ -1,155 +0,0 @@
<?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>This value should be false.</source>
<target>Verdien skal være falsk.</target>
</trans-unit>
<trans-unit id="2">
<source>This value should be true.</source>
<target>Verdien skal være sann.</target>
</trans-unit>
<trans-unit id="3">
<source>This value should be of type {{ type }}.</source>
<target>Verdien skal være av typen {{ type }}.</target>
</trans-unit>
<trans-unit id="4">
<source>This value should be blank.</source>
<target>Verdien skal være blank.</target>
</trans-unit>
<trans-unit id="5">
<source>The value you selected is not a valid choice.</source>
<target>Verdien skal være en av de gitte valg.</target>
</trans-unit>
<trans-unit id="6">
<source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
<target>Du skal velge minst {{ limit }} valg.</target>
</trans-unit>
<trans-unit id="7">
<source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
<target>Du kan maks velge {{ limit }} valg.</target>
</trans-unit>
<trans-unit id="8">
<source>One or more of the given values is invalid.</source>
<target>En eller flere av de oppgitte verdier er ugyldige.</target>
</trans-unit>
<trans-unit id="9">
<source>This field was not expected.</source>
<target>Dette feltet ikke var forventet.</target>
</trans-unit>
<trans-unit id="10">
<source>This field is missing.</source>
<target>Dette feltet mangler.</target>
</trans-unit>
<trans-unit id="11">
<source>This value is not a valid date.</source>
<target>Verdien er ikke en gyldig dato.</target>
</trans-unit>
<trans-unit id="12">
<source>This value is not a valid datetime.</source>
<target>Verdien er ikke en gyldig dato og tid.</target>
</trans-unit>
<trans-unit id="13">
<source>This value is not a valid email address.</source>
<target>Verdien er ikke en gyldig e-mail adresse.</target>
</trans-unit>
<trans-unit id="14">
<source>The file could not be found.</source>
<target>Filen kunne ikke finnes.</target>
</trans-unit>
<trans-unit id="15">
<source>The file is not readable.</source>
<target>Filen kan ikke leses.</target>
</trans-unit>
<trans-unit id="16">
<source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
<target>Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}.</target>
</trans-unit>
<trans-unit id="17">
<source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
<target>Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}.</target>
</trans-unit>
<trans-unit id="18">
<source>This value should be {{ limit }} or less.</source>
<target>Verdien skal være {{ limit }} eller mindre.</target>
</trans-unit>
<trans-unit id="19">
<source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
<target>Verdien er for lang. Den skal ha {{ limit }} bokstaver eller mindre.</target>
</trans-unit>
<trans-unit id="20">
<source>This value should be {{ limit }} or more.</source>
<target>Verdien skal være {{ limit }} eller mer.</target>
</trans-unit>
<trans-unit id="21">
<source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
<target>Verdien er for kort. Den skal ha {{ limit }} tegn eller flere.</target>
</trans-unit>
<trans-unit id="22">
<source>This value should not be blank.</source>
<target>Verdien må ikke være blank.</target>
</trans-unit>
<trans-unit id="23">
<source>This value should not be null.</source>
<target>Verdien må ikke være tom (null).</target>
</trans-unit>
<trans-unit id="24">
<source>This value should be null.</source>
<target>Verdien skal være tom (null).</target>
</trans-unit>
<trans-unit id="25">
<source>This value is not valid.</source>
<target>Verdien er ikke gyldig.</target>
</trans-unit>
<trans-unit id="26">
<source>This value is not a valid time.</source>
<target>Verdien er ikke en gyldig tid.</target>
</trans-unit>
<trans-unit id="27">
<source>This value is not a valid URL.</source>
<target>Verdien er ikke en gyldig URL.</target>
</trans-unit>
<trans-unit id="31">
<source>The two values should be equal.</source>
<target>De to verdier skal være ens.</target>
</trans-unit>
<trans-unit id="32">
<source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
<target>Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}.</target>
</trans-unit>
<trans-unit id="33">
<source>The file is too large.</source>
<target>Filen er for stor.</target>
</trans-unit>
<trans-unit id="34">
<source>The file could not be uploaded.</source>
<target>Filen kunne ikke lastes opp.</target>
</trans-unit>
<trans-unit id="35">
<source>This value should be a valid number.</source>
<target>Denne verdi skal være et gyldig tall.</target>
</trans-unit>
<trans-unit id="36">
<source>This file is not a valid image.</source>
<target>Denne filen er ikke et gyldig bilde.</target>
</trans-unit>
<trans-unit id="37">
<source>This is not a valid IP address.</source>
<target>Dette er ikke en gyldig IP adresse.</target>
</trans-unit>
<trans-unit id="38">
<source>This value is not a valid language.</source>
<target>Denne verdi er ikke et gyldig språk.</target>
</trans-unit>
<trans-unit id="39">
<source>This value is not a valid locale.</source>
<target>Denne verdi er ikke en gyldig lokalitet.</target>
</trans-unit>
<trans-unit id="40">
<source>This value is not a valid country.</source>
<target>Denne verdi er ikke et gyldig land.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -0,0 +1,227 @@
<?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>This value should be false.</source>
<target>Verdien skulle ha vore tom/nei.</target>
</trans-unit>
<trans-unit id="2">
<source>This value should be true.</source>
<target>Verdien skulla ha vore satt/ja.</target>
</trans-unit>
<trans-unit id="3">
<source>This value should be of type {{ type }}.</source>
<target>Verdien må vere av typen {{ type }}.</target>
</trans-unit>
<trans-unit id="4">
<source>This value should be blank.</source>
<target>Verdien skal vere blank.</target>
</trans-unit>
<trans-unit id="5">
<source>The value you selected is not a valid choice.</source>
<target>Verdien du valgte er ikkje gyldig.</target>
</trans-unit>
<trans-unit id="6">
<source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
<target>Du må velge minst {{ limit }} valg.</target>
</trans-unit>
<trans-unit id="7">
<source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
<target>Du kan maksimalt gjere {{ limit }} valg.</target>
</trans-unit>
<trans-unit id="8">
<source>One or more of the given values is invalid.</source>
<target>Ein eller fleire av dei opplyste verdiane er ugyldige.</target>
</trans-unit>
<trans-unit id="9">
<source>This field was not expected.</source>
<target>Dette feltet var ikke forventet.</target>
</trans-unit>
<trans-unit id="10">
<source>This field is missing.</source>
<target>Dette feltet mangler.</target>
</trans-unit>
<trans-unit id="11">
<source>This value is not a valid date.</source>
<target>Verdien er ikkje ein gyldig dato.</target>
</trans-unit>
<trans-unit id="12">
<source>This value is not a valid datetime.</source>
<target>Verdien er ikkje ein gyldig dato og tid.</target>
</trans-unit>
<trans-unit id="13">
<source>This value is not a valid email address.</source>
<target>Verdien er ikkje ei gyldig e-postadresse.</target>
</trans-unit>
<trans-unit id="14">
<source>The file could not be found.</source>
<target>Fila kunne ikkje finnes.</target>
</trans-unit>
<trans-unit id="15">
<source>The file is not readable.</source>
<target>Fila kan ikkje lesast.</target>
</trans-unit>
<trans-unit id="16">
<source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
<target>Fila er for stor ({{ size }} {{ suffix }}). Tillatt maksimal størrelse er {{ limit }} {{ suffix }}.</target>
</trans-unit>
<trans-unit id="17">
<source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
<target>Mime-typen av fila er ugyldig ({{ type }}). Tillatte mime-typar er {{ types }}.</target>
</trans-unit>
<trans-unit id="18">
<source>This value should be {{ limit }} or less.</source>
<target>Verdien må vere {{ limit }} eller mindre.</target>
</trans-unit>
<trans-unit id="19">
<source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
<target>Verdien er for lang. Den må vere {{ limit }} bokstavar eller mindre.</target>
</trans-unit>
<trans-unit id="20">
<source>This value should be {{ limit }} or more.</source>
<target>Verdien må vere {{ limit }} eller meir.</target>
</trans-unit>
<trans-unit id="21">
<source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
<target>Verdien er for kort. Den må ha {{ limit }} teikn eller fleire.</target>
</trans-unit>
<trans-unit id="22">
<source>This value should not be blank.</source>
<target>Verdien må ikkje vere blank.</target>
</trans-unit>
<trans-unit id="23">
<source>This value should not be null.</source>
<target>Verdien må ikkje vere tom (null).</target>
</trans-unit>
<trans-unit id="24">
<source>This value should be null.</source>
<target>Verdien må vere tom (null).</target>
</trans-unit>
<trans-unit id="25">
<source>This value is not valid.</source>
<target>Verdien er ikkje gyldig.</target>
</trans-unit>
<trans-unit id="26">
<source>This value is not a valid time.</source>
<target>Verdien er ikkje gyldig tidseining.</target>
</trans-unit>
<trans-unit id="27">
<source>This value is not a valid URL.</source>
<target>Verdien er ikkje ein gyldig URL.</target>
</trans-unit>
<trans-unit id="31">
<source>The two values should be equal.</source>
<target>Dei to verdiane må vere like.</target>
</trans-unit>
<trans-unit id="32">
<source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
<target>Fila er for stor. Den maksimale storleik er {{ limit }} {{ suffix }}.</target>
</trans-unit>
<trans-unit id="33">
<source>The file is too large.</source>
<target>Fila er for stor.</target>
</trans-unit>
<trans-unit id="34">
<source>The file could not be uploaded.</source>
<target>Fila kunne ikkje bli lasta opp.</target>
</trans-unit>
<trans-unit id="35">
<source>This value should be a valid number.</source>
<target>Verdien må vere eit gyldig tal.</target>
</trans-unit>
<trans-unit id="36">
<source>This file is not a valid image.</source>
<target>Fila er ikkje eit gyldig bilete.</target>
</trans-unit>
<trans-unit id="37">
<source>This is not a valid IP address.</source>
<target>Dette er ikkje ei gyldig IP-adresse.</target>
</trans-unit>
<trans-unit id="38">
<source>This value is not a valid language.</source>
<target>Verdien er ikkje eit gyldig språk.</target>
</trans-unit>
<trans-unit id="39">
<source>This value is not a valid locale.</source>
<target>Verdien er ikkje ein gyldig lokalitet (språk/region).</target>
</trans-unit>
<trans-unit id="40">
<source>This value is not a valid country.</source>
<target>Verdien er ikkje eit gyldig land.</target>
</trans-unit>
<trans-unit id="41">
<source>This value is already used.</source>
<target>Verdien er allereie i bruk.</target>
</trans-unit>
<trans-unit id="42">
<source>The size of the image could not be detected.</source>
<target>Storleiken på biletet kunne ikkje oppdagast.</target>
</trans-unit>
<trans-unit id="43">
<source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
<target>Biletbreidda er for stor, ({{ width }} pikslar). Tillatt maksimumsbreidde er {{ max_width }} pikslar.</target>
</trans-unit>
<trans-unit id="44">
<source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
<target>Biletbreidda er for liten, ({{ width }} pikslar). Forventa minimumsbreidde er {{ min_width }} pikslar.</target>
</trans-unit>
<trans-unit id="45">
<source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
<target>Bilethøgda er for stor, ({{ height }} pikslar). Tillatt maksimumshøgde er {{ max_height }} pikslar.</target>
</trans-unit>
<trans-unit id="46">
<source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
<target>Billethøgda er for låg, ({{ height }} pikslar). Forventa minimumshøgde er {{ min_height }} pikslar.</target>
</trans-unit>
<trans-unit id="47">
<source>This value should be the user's current password.</source>
<target>Verdien må vere brukaren sitt noverande passord.</target>
</trans-unit>
<trans-unit id="48">
<source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
<target>Verdien må vere nøyaktig {{ limit }} teikn.</target>
</trans-unit>
<trans-unit id="49">
<source>The file was only partially uploaded.</source>
<target>Fila vart kun delvis opplasta.</target>
</trans-unit>
<trans-unit id="50">
<source>No file was uploaded.</source>
<target>Inga fil vart lasta opp.</target>
</trans-unit>
<trans-unit id="51">
<source>No temporary folder was configured in php.ini.</source>
<target>Førebels mappe (tmp) er ikkje konfigurert i php.ini.</target>
</trans-unit>
<trans-unit id="52">
<source>Cannot write temporary file to disk.</source>
<target>Kan ikkje skrive førebels fil til disk.</target>
</trans-unit>
<trans-unit id="53">
<source>A PHP extension caused the upload to fail.</source>
<target>Ei PHP-udviding forårsaka feil under opplasting.</target>
</trans-unit>
<trans-unit id="54">
<source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
<target>Denne samlinga må innehalde {{ limit }} element eller meir.|Denne samlinga må innehalde {{ limit }} element eller meir.</target>
</trans-unit>
<trans-unit id="55">
<source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
<target>Denne samlinga må innehalde {{ limit }} element eller færre.|Denne samlinga må innehalde {{ limit }} element eller færre.</target>
</trans-unit>
<trans-unit id="56">
<source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
<target>Denne samlinga må innehalde nøyaktig {{ limit }} element.|Denne samlinga må innehalde nøyaktig {{ limit }} element.</target>
</trans-unit>
<trans-unit id="57">
<source>Invalid card number.</source>
<target>Ugyldig kortnummer.</target>
</trans-unit>
<trans-unit id="58">
<source>Unsupported card type or invalid card number.</source>
<target>Korttypen er ikkje støtta eller ugyldig kortnummer.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -4,39 +4,39 @@
<body> <body>
<trans-unit id="1"> <trans-unit id="1">
<source>This value should be false.</source> <source>This value should be false.</source>
<target>Verdien skulle ha vore tom/nei.</target> <target>Verdien skal være falsk.</target>
</trans-unit> </trans-unit>
<trans-unit id="2"> <trans-unit id="2">
<source>This value should be true.</source> <source>This value should be true.</source>
<target>Verdien skulla ha vore satt/ja.</target> <target>Verdien skal være sann.</target>
</trans-unit> </trans-unit>
<trans-unit id="3"> <trans-unit id="3">
<source>This value should be of type {{ type }}.</source> <source>This value should be of type {{ type }}.</source>
<target>Verdien må vere av typen {{ type }}.</target> <target>Verdien skal være av typen {{ type }}.</target>
</trans-unit> </trans-unit>
<trans-unit id="4"> <trans-unit id="4">
<source>This value should be blank.</source> <source>This value should be blank.</source>
<target>Verdien skal vere blank.</target> <target>Verdien skal være blank.</target>
</trans-unit> </trans-unit>
<trans-unit id="5"> <trans-unit id="5">
<source>The value you selected is not a valid choice.</source> <source>The value you selected is not a valid choice.</source>
<target>Verdien du valgte er ikkje gyldig.</target> <target>Verdien skal være en av de gitte valg.</target>
</trans-unit> </trans-unit>
<trans-unit id="6"> <trans-unit id="6">
<source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source> <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
<target>Du velge minst {{ limit }} valg.</target> <target>Du skal velge minst {{ limit }} valg.</target>
</trans-unit> </trans-unit>
<trans-unit id="7"> <trans-unit id="7">
<source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source> <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
<target>Du kan maksimalt gjere {{ limit }} valg.</target> <target>Du kan maks velge {{ limit }} valg.</target>
</trans-unit> </trans-unit>
<trans-unit id="8"> <trans-unit id="8">
<source>One or more of the given values is invalid.</source> <source>One or more of the given values is invalid.</source>
<target>Ein eller fleire av dei opplyste verdiane er ugyldige.</target> <target>En eller flere av de oppgitte verdier er ugyldige.</target>
</trans-unit> </trans-unit>
<trans-unit id="9"> <trans-unit id="9">
<source>This field was not expected.</source> <source>This field was not expected.</source>
<target>Dette feltet var ikke forventet.</target> <target>Dette feltet ikke var forventet.</target>
</trans-unit> </trans-unit>
<trans-unit id="10"> <trans-unit id="10">
<source>This field is missing.</source> <source>This field is missing.</source>
@ -44,183 +44,111 @@
</trans-unit> </trans-unit>
<trans-unit id="11"> <trans-unit id="11">
<source>This value is not a valid date.</source> <source>This value is not a valid date.</source>
<target>Verdien er ikkje ein gyldig dato.</target> <target>Verdien er ikke en gyldig dato.</target>
</trans-unit> </trans-unit>
<trans-unit id="12"> <trans-unit id="12">
<source>This value is not a valid datetime.</source> <source>This value is not a valid datetime.</source>
<target>Verdien er ikkje ein gyldig dato og tid.</target> <target>Verdien er ikke en gyldig dato og tid.</target>
</trans-unit> </trans-unit>
<trans-unit id="13"> <trans-unit id="13">
<source>This value is not a valid email address.</source> <source>This value is not a valid email address.</source>
<target>Verdien er ikkje ei gyldig e-postadresse.</target> <target>Verdien er ikke en gyldig e-mail adresse.</target>
</trans-unit> </trans-unit>
<trans-unit id="14"> <trans-unit id="14">
<source>The file could not be found.</source> <source>The file could not be found.</source>
<target>Fila kunne ikkje finnes.</target> <target>Filen kunne ikke finnes.</target>
</trans-unit> </trans-unit>
<trans-unit id="15"> <trans-unit id="15">
<source>The file is not readable.</source> <source>The file is not readable.</source>
<target>Fila kan ikkje lesast.</target> <target>Filen kan ikke leses.</target>
</trans-unit> </trans-unit>
<trans-unit id="16"> <trans-unit id="16">
<source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source> <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
<target>Fila er for stor ({{ size }} {{ suffix }}). Tillatt maksimal størrelse er {{ limit }} {{ suffix }}.</target> <target>Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}.</target>
</trans-unit> </trans-unit>
<trans-unit id="17"> <trans-unit id="17">
<source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source> <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
<target>Mime-typen av fila er ugyldig ({{ type }}). Tillatte mime-typar er {{ types }}.</target> <target>Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}.</target>
</trans-unit> </trans-unit>
<trans-unit id="18"> <trans-unit id="18">
<source>This value should be {{ limit }} or less.</source> <source>This value should be {{ limit }} or less.</source>
<target>Verdien må vere {{ limit }} eller mindre.</target> <target>Verdien skal være {{ limit }} eller mindre.</target>
</trans-unit> </trans-unit>
<trans-unit id="19"> <trans-unit id="19">
<source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source> <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
<target>Verdien er for lang. Den må vere {{ limit }} bokstavar eller mindre.</target> <target>Verdien er for lang. Den skal ha {{ limit }} bokstaver eller mindre.</target>
</trans-unit> </trans-unit>
<trans-unit id="20"> <trans-unit id="20">
<source>This value should be {{ limit }} or more.</source> <source>This value should be {{ limit }} or more.</source>
<target>Verdien må vere {{ limit }} eller meir.</target> <target>Verdien skal være {{ limit }} eller mer.</target>
</trans-unit> </trans-unit>
<trans-unit id="21"> <trans-unit id="21">
<source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source> <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
<target>Verdien er for kort. Den må ha {{ limit }} teikn eller fleire.</target> <target>Verdien er for kort. Den skal ha {{ limit }} tegn eller flere.</target>
</trans-unit> </trans-unit>
<trans-unit id="22"> <trans-unit id="22">
<source>This value should not be blank.</source> <source>This value should not be blank.</source>
<target>Verdien må ikkje vere blank.</target> <target>Verdien må ikke være blank.</target>
</trans-unit> </trans-unit>
<trans-unit id="23"> <trans-unit id="23">
<source>This value should not be null.</source> <source>This value should not be null.</source>
<target>Verdien må ikkje vere tom (null).</target> <target>Verdien må ikke være tom (null).</target>
</trans-unit> </trans-unit>
<trans-unit id="24"> <trans-unit id="24">
<source>This value should be null.</source> <source>This value should be null.</source>
<target>Verdien må vere tom (null).</target> <target>Verdien skal være tom (null).</target>
</trans-unit> </trans-unit>
<trans-unit id="25"> <trans-unit id="25">
<source>This value is not valid.</source> <source>This value is not valid.</source>
<target>Verdien er ikkje gyldig.</target> <target>Verdien er ikke gyldig.</target>
</trans-unit> </trans-unit>
<trans-unit id="26"> <trans-unit id="26">
<source>This value is not a valid time.</source> <source>This value is not a valid time.</source>
<target>Verdien er ikkje gyldig tidseining.</target> <target>Verdien er ikke en gyldig tid.</target>
</trans-unit> </trans-unit>
<trans-unit id="27"> <trans-unit id="27">
<source>This value is not a valid URL.</source> <source>This value is not a valid URL.</source>
<target>Verdien er ikkje ein gyldig URL.</target> <target>Verdien er ikke en gyldig URL.</target>
</trans-unit> </trans-unit>
<trans-unit id="31"> <trans-unit id="31">
<source>The two values should be equal.</source> <source>The two values should be equal.</source>
<target>Dei to verdiane må vere like.</target> <target>De to verdier skal være ens.</target>
</trans-unit> </trans-unit>
<trans-unit id="32"> <trans-unit id="32">
<source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source> <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
<target>Fila er for stor. Den maksimale storleik er {{ limit }} {{ suffix }}.</target> <target>Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}.</target>
</trans-unit> </trans-unit>
<trans-unit id="33"> <trans-unit id="33">
<source>The file is too large.</source> <source>The file is too large.</source>
<target>Fila er for stor.</target> <target>Filen er for stor.</target>
</trans-unit> </trans-unit>
<trans-unit id="34"> <trans-unit id="34">
<source>The file could not be uploaded.</source> <source>The file could not be uploaded.</source>
<target>Fila kunne ikkje bli lasta opp.</target> <target>Filen kunne ikke lastes opp.</target>
</trans-unit> </trans-unit>
<trans-unit id="35"> <trans-unit id="35">
<source>This value should be a valid number.</source> <source>This value should be a valid number.</source>
<target>Verdien må vere eit gyldig tal.</target> <target>Denne verdi skal være et gyldig tall.</target>
</trans-unit> </trans-unit>
<trans-unit id="36"> <trans-unit id="36">
<source>This file is not a valid image.</source> <source>This file is not a valid image.</source>
<target>Fila er ikkje eit gyldig bilete.</target> <target>Denne filen er ikke et gyldig bilde.</target>
</trans-unit> </trans-unit>
<trans-unit id="37"> <trans-unit id="37">
<source>This is not a valid IP address.</source> <source>This is not a valid IP address.</source>
<target>Dette er ikkje ei gyldig IP-adresse.</target> <target>Dette er ikke en gyldig IP adresse.</target>
</trans-unit> </trans-unit>
<trans-unit id="38"> <trans-unit id="38">
<source>This value is not a valid language.</source> <source>This value is not a valid language.</source>
<target>Verdien er ikkje eit gyldig språk.</target> <target>Denne verdi er ikke et gyldig språk.</target>
</trans-unit> </trans-unit>
<trans-unit id="39"> <trans-unit id="39">
<source>This value is not a valid locale.</source> <source>This value is not a valid locale.</source>
<target>Verdien er ikkje ein gyldig lokalitet (språk/region).</target> <target>Denne verdi er ikke en gyldig lokalitet.</target>
</trans-unit> </trans-unit>
<trans-unit id="40"> <trans-unit id="40">
<source>This value is not a valid country.</source> <source>This value is not a valid country.</source>
<target>Verdien er ikkje eit gyldig land.</target> <target>Denne verdi er ikke et gyldig land.</target>
</trans-unit>
<trans-unit id="41">
<source>This value is already used.</source>
<target>Verdien er allereie i bruk.</target>
</trans-unit>
<trans-unit id="42">
<source>The size of the image could not be detected.</source>
<target>Storleiken på biletet kunne ikkje oppdagast.</target>
</trans-unit>
<trans-unit id="43">
<source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
<target>Biletbreidda er for stor, ({{ width }} pikslar). Tillatt maksimumsbreidde er {{ max_width }} pikslar.</target>
</trans-unit>
<trans-unit id="44">
<source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
<target>Biletbreidda er for liten, ({{ width }} pikslar). Forventa minimumsbreidde er {{ min_width }} pikslar.</target>
</trans-unit>
<trans-unit id="45">
<source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
<target>Bilethøgda er for stor, ({{ height }} pikslar). Tillatt maksimumshøgde er {{ max_height }} pikslar.</target>
</trans-unit>
<trans-unit id="46">
<source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
<target>Billethøgda er for låg, ({{ height }} pikslar). Forventa minimumshøgde er {{ min_height }} pikslar.</target>
</trans-unit>
<trans-unit id="47">
<source>This value should be the user's current password.</source>
<target>Verdien må vere brukaren sitt noverande passord.</target>
</trans-unit>
<trans-unit id="48">
<source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
<target>Verdien må vere nøyaktig {{ limit }} teikn.</target>
</trans-unit>
<trans-unit id="49">
<source>The file was only partially uploaded.</source>
<target>Fila vart kun delvis opplasta.</target>
</trans-unit>
<trans-unit id="50">
<source>No file was uploaded.</source>
<target>Inga fil vart lasta opp.</target>
</trans-unit>
<trans-unit id="51">
<source>No temporary folder was configured in php.ini.</source>
<target>Førebels mappe (tmp) er ikkje konfigurert i php.ini.</target>
</trans-unit>
<trans-unit id="52">
<source>Cannot write temporary file to disk.</source>
<target>Kan ikkje skrive førebels fil til disk.</target>
</trans-unit>
<trans-unit id="53">
<source>A PHP extension caused the upload to fail.</source>
<target>Ei PHP-udviding forårsaka feil under opplasting.</target>
</trans-unit>
<trans-unit id="54">
<source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
<target>Denne samlinga må innehalde {{ limit }} element eller meir.|Denne samlinga må innehalde {{ limit }} element eller meir.</target>
</trans-unit>
<trans-unit id="55">
<source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
<target>Denne samlinga må innehalde {{ limit }} element eller færre.|Denne samlinga må innehalde {{ limit }} element eller færre.</target>
</trans-unit>
<trans-unit id="56">
<source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
<target>Denne samlinga må innehalde nøyaktig {{ limit }} element.|Denne samlinga må innehalde nøyaktig {{ limit }} element.</target>
</trans-unit>
<trans-unit id="57">
<source>Invalid card number.</source>
<target>Ugyldig kortnummer.</target>
</trans-unit>
<trans-unit id="58">
<source>Unsupported card type or invalid card number.</source>
<target>Korttypen er ikkje støtta eller ugyldig kortnummer.</target>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -301,8 +301,14 @@ class Parser
mb_internal_encoding($mbEncoding); mb_internal_encoding($mbEncoding);
} }
if ($objectForMap && !is_object($data)) { if ($objectForMap && !is_object($data) && 'mapping' === $context) {
$data = (object) $data; $object = new \stdClass();
foreach ($data as $key => $value) {
$object->$key = $value;
}
$data = $object;
} }
return empty($data) ? null : $data; return empty($data) ? null : $data;

View File

@ -442,35 +442,75 @@ EOF;
$this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects'); $this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects');
} }
public function testObjectForMapEnabledWithMapping() /**
* @dataProvider getObjectForMapTests
*/
public function testObjectForMap($yaml, $expected)
{ {
$this->assertEquals($expected, $this->parser->parse($yaml, false, false, true));
}
public function getObjectForMapTests()
{
$tests = array();
$yaml = <<<EOF $yaml = <<<EOF
foo: foo:
fiz: [cat] fiz: [cat]
EOF; EOF;
$result = $this->parser->parse($yaml, false, false, true); $expected = new \stdClass();
$expected->foo = new \stdClass();
$expected->foo->fiz = array('cat');
$tests['mapping'] = array($yaml, $expected);
$this->assertInstanceOf('stdClass', $result); $yaml = '{ "foo": "bar", "fiz": "cat" }';
$this->assertInstanceOf('stdClass', $result->foo); $expected = new \stdClass();
$this->assertEquals(array('cat'), $result->foo->fiz); $expected->foo = 'bar';
} $expected->fiz = 'cat';
$tests['inline-mapping'] = array($yaml, $expected);
public function testObjectForMapEnabledWithInlineMapping() $yaml = "foo: bar\nbaz: foobar";
{
$result = $this->parser->parse('{ "foo": "bar", "fiz": "cat" }', false, false, true);
$this->assertInstanceOf('stdClass', $result);
$this->assertEquals('bar', $result->foo);
$this->assertEquals('cat', $result->fiz);
}
public function testObjectForMapIsAppliedAfterParsing()
{
$expected = new \stdClass(); $expected = new \stdClass();
$expected->foo = 'bar'; $expected->foo = 'bar';
$expected->baz = 'foobar'; $expected->baz = 'foobar';
$tests['object-for-map-is-applied-after-parsing'] = array($yaml, $expected);
$this->assertEquals($expected, $this->parser->parse("foo: bar\nbaz: foobar", false, false, true)); $yaml = <<<EOT
array:
- key: one
- key: two
EOT;
$expected = new \stdClass();
$expected->array = array();
$expected->array[0] = new \stdClass();
$expected->array[0]->key = 'one';
$expected->array[1] = new \stdClass();
$expected->array[1]->key = 'two';
$tests['nest-map-and-sequence'] = array($yaml, $expected);
$yaml = <<<YAML
map:
1: one
2: two
YAML;
$expected = new \stdClass();
$expected->map = new \stdClass();
$expected->map->{1} = 'one';
$expected->map->{2} = 'two';
$tests['numeric-keys'] = array($yaml, $expected);
$yaml = <<<YAML
map:
0: one
1: two
YAML;
$expected = new \stdClass();
$expected->map = new \stdClass();
$expected->map->{0} = 'one';
$expected->map->{1} = 'two';
$tests['zero-indexed-numeric-keys'] = array($yaml, $expected);
return $tests;
} }
/** /**