/** * @param \Twig_NodeInterface $node * @param \Twig_Environment $env * @return \Twig_NodeInterface */ public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) { $this->stack[] = $node; if ($node instanceof TransNode) { $id = $node->getNode('body')->getAttribute('data'); $domain = 'messages'; if (null !== ($domainNode = $node->getNode('domain'))) { $domain = $domainNode->getAttribute('value'); } $message = new Message($id, $domain); $message->addSource($this->fileSourceFactory->create($this->file, $node->getLine())); $this->catalogue->add($message); } elseif ($node instanceof \Twig_Node_Expression_Filter) { $name = $node->getNode('filter')->getAttribute('value'); if ('trans' === $name || 'transchoice' === $name) { $idNode = $node->getNode('node'); if (!$idNode instanceof \Twig_Node_Expression_Constant) { return $node; // FIXME: see below // throw new \RuntimeException(sprintf('Cannot infer translation id from node "%s". Please refactor to only translate constants.', get_class($idNode))); } $id = $idNode->getAttribute('value'); $index = 'trans' === $name ? 1 : 2; $domain = 'messages'; $arguments = $node->getNode('arguments'); if ($arguments->hasNode($index)) { $argument = $arguments->getNode($index); if (!$argument instanceof \Twig_Node_Expression_Constant) { return $node; // FIXME: Throw exception if there is some way for the user to turn this off // on a case-by-case basis, similar to @Ignore in PHP } $domain = $argument->getAttribute('value'); } $message = new Message($id, $domain); $message->addSource($this->fileSourceFactory->create($this->file, $node->getLine())); for ($i = count($this->stack) - 2; $i >= 0; $i -= 1) { if (!$this->stack[$i] instanceof \Twig_Node_Expression_Filter) { break; } $name = $this->stack[$i]->getNode('filter')->getAttribute('value'); if ('desc' === $name || 'meaning' === $name) { $arguments = $this->stack[$i]->getNode('arguments'); if (!$arguments->hasNode(0)) { throw new RuntimeException(sprintf('The "%s" filter requires exactly one argument, the description text.', $name)); } $text = $arguments->getNode(0); if (!$text instanceof \Twig_Node_Expression_Constant) { throw new RuntimeException(sprintf('The first argument of the "%s" filter must be a constant expression, such as a string.', $name)); } $message->{'set' . $name}($text->getAttribute('value')); } elseif ('trans' === $name) { break; } } $this->catalogue->add($message); } } return $node; }
/** * Get the translations * * @return MessageCatalogue */ protected function getTranslations() { $catalogue = new MessageCatalogue(); $labels = array(); $entities = $this->getEntities(); foreach ($entities as $entity) { $labels[] = $entity . '.label'; $labels[] = $entity . '.show.title'; $labels[] = $entity . '.edit.title'; $labels[] = $entity . '.list.title'; $labels[] = $entity . '.new.title'; $labels[] = $entity . '.delete.title'; } //avoid doublons $uniqueLabels = array_unique($labels); foreach ($uniqueLabels as $uniqueLabel) { $message = new Message($uniqueLabel, $this->domain); $catalogue->add($message); } if ($this->customizedFlash) { $flashLabels = $this->getFlashsLabels($entities); foreach ($flashLabels as $flashLabel) { $message = new Message($flashLabel, $this->domain); $catalogue->add($message); } } return $catalogue; }
public function testPathWithSubPath() { $catalogue = new MessageCatalogue(); $catalogue->setLocale('fr'); $catalogue->add(new Message('foo.bar')); $catalogue->add(new Message('foo.bar.baz')); $dumper = $this->getDumper(); $dumper->expects($this->once())->method('dumpStructure')->with(array('foo' => array('bar' => new Message('foo.bar'), 'bar.baz' => new Message('foo.bar.baz'))))->will($this->returnValue('foo')); $this->assertEquals('foo', $dumper->dump($catalogue, 'messages')); }
public function testLoadWithSymfonyFormat() { $loader = new XliffLoader(); $expected = new MessageCatalogue(); $expected->setLocale('en'); $expected->add(XliffMessage::create('foo1')->setDesc('foo1')->setLocaleString('bar')->setNew(false)); $expected->add(XliffMessage::create('foo2')->setDesc('foo2')->setLocaleString('bar')->setNew(false)); $expected->add(XliffMessage::create('foo3')->setDesc('foo3')->setLocaleString('bar')->setNew(false)); $expected->add(XliffMessage::create('foo4')->setDesc('foo4')->setLocaleString('bar')->setNew(false)); $this->assertEquals($expected, $loader->load(__DIR__ . '/Symfony/xliff/old_format.xml', 'en')); }
public function testCompareWithMultipleDomains() { $current = new MessageCatalogue(); $current->add(Message::create('foo')->setLocaleString('bar')); $current->add(Message::create('bar', 'routes')->setLocaleString('baz')); $new = new MessageCatalogue(); $new->add(new Message('foo')); $new->add(new Message('bar')); $expected = new ChangeSet(array(new Message('bar')), array(Message::create('bar', 'routes')->setLocaleString('baz'))); $comparator = new CatalogueComparator(); $this->assertEquals($expected, $comparator->compare($current, $new)); }
public function testExtractFormModel() { $expected = new MessageCatalogue(); $path = __DIR__ . '/Fixture/MyFormModel.php'; $message = new Message('form.label.choice.foo'); $message->addSource(new FileSource($path, 13)); $expected->add($message); $message = new Message('form.label.choice.bar'); $message->addSource(new FileSource($path, 13)); $expected->add($message); $this->assertEquals($expected, $this->extract('MyFormModel.php')); }
public function testExtractTemplate() { $expected = new MessageCatalogue(); $path = __DIR__ . '/Fixture/template.html.php'; $message = new Message('foo.bar'); $message->addSource(new FileSource($path, 1)); $expected->add($message); $message = new Message('baz', 'moo'); $message->setDesc('Foo Bar'); $message->addSource(new FileSource($path, 3)); $expected->add($message); $this->assertEquals($expected, $this->extract('template.html.php')); }
public function testExtractValidationMessages() { $fileSourceFactory = $this->getFileSourceFactory(); $fixtureSplInfo = new \SplFileInfo(__DIR__ . '/Fixture/MyEntity.php'); $expected = new MessageCatalogue(); $message = new Message('entity.default'); $message->addSource($fileSourceFactory->create($fixtureSplInfo, 15)); $expected->add($message); $message = new Message('entity.custom-domain', 'custom-domain'); $message->addSource($fileSourceFactory->create($fixtureSplInfo, 22)); $expected->add($message); $this->assertEquals($expected, $this->extract('MyEntity.php')); }
public function testExtract() { $expected = new MessageCatalogue(); $message = new Message('security.authentication_error.foo', 'authentication'); $message->setDesc('%foo% is invalid.'); $message->addSource(new FileSource(__DIR__ . '/Fixture/MyAuthException.php', 31)); $expected->add($message); $message = new Message('security.authentication_error.bar', 'authentication'); $message->setDesc('An authentication error occurred.'); $message->addSource(new FileSource(__DIR__ . '/Fixture/MyAuthException.php', 35)); $expected->add($message); $this->assertEquals($expected, $this->extract('MyAuthException.php')); }
public function testExtractTemplate() { $expected = new MessageCatalogue(); $fileSourceFactory = $this->getFileSourceFactory(); $fixtureSplInfo = new \SplFileInfo(__DIR__ . '/Fixture/template.html.php'); $message = new Message('foo.bar'); $message->addSource($fileSourceFactory->create($fixtureSplInfo, 1)); $expected->add($message); $message = new Message('baz', 'moo'); $message->setDesc('Foo Bar'); $message->addSource($fileSourceFactory->create($fixtureSplInfo, 3)); $expected->add($message); $this->assertEquals($expected, $this->extract('template.html.php')); }
public function testDumpStructureWithMetadata() { $catalogue = new MessageCatalogue(); $catalogue->setLocale('en'); $message = new Message('foo.bar.baz'); $message->setDesc('Foo'); $catalogue->add($message); $message = new Message('foo.bar.moo'); $message->setMeaning('Bar'); $catalogue->add($message); $message = new Message('foo.baz'); $catalogue->add($message); $this->assertEquals($this->getOutput('structure_with_metadata'), $this->dump($catalogue, 'messages')); }
public function testCatalogueIsSortedBeforeBeingDumped() { $dumper = $this->getMock('JMS\\TranslationBundle\\Translation\\Dumper\\DumperInterface'); $self = $this; $dumper->expects($this->once())->method('dump')->will($this->returnCallback(function ($v) use($self) { $self->assertEquals(array('foo.bar', 'foo.bar.baz'), array_keys($v->getDomain('messages')->all())); })); $writer = new FileWriter(array('test' => $dumper)); $catalogue = new MessageCatalogue(); $catalogue->setLocale('fr'); $catalogue->add(new Message('foo.bar.baz')); $catalogue->add(new Message('foo.bar')); $path = tempnam(sys_get_temp_dir(), 'filewriter'); $writer->write($catalogue, 'messages', $path, 'test'); @unlink($path); }
public function testCdataOutput() { $dumper = $this->getDumper(); $catalogue = new MessageCatalogue(); $catalogue->add(Message::create('foo')->setLocaleString('<bar>')->setDesc('<baz>')); $expected = <<<EOF <?xml version="1.0" encoding="utf-8"?> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <file source-language="en" target-language="" datatype="plaintext" original="not.available"> <header> <tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/> <note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note> </header> <body> <trans-unit id="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" resname="foo"> <source><![CDATA[<baz>]]></source> <target state="new"><![CDATA[<bar>]]></target> </trans-unit> </body> </file> </xliff> EOF; $this->assertEquals($expected, $dumper->dump($catalogue, 'messages')); }
public function write(MessageCatalogue $catalogue, $domain, $filePath, $format) { $newCatalogue = new MessageCatalogue(); $newCatalogue->setLocale($catalogue->getLocale()); foreach (array_keys($catalogue->getDomains()) as $catalogueDomainString) { if ($catalogue->getLocale() !== 'en' && $this->hasEnglishCatalogue($filePath)) { $englishCatalogue = $this->loadEnglishCatalogue($filePath, $domain, $format); } $domainMessageCollection = $catalogue->getDomain($catalogueDomainString); /** @var Message $message */ foreach ($domainMessageCollection->all() as $message) { if ($message->getDomain() !== $domain) { continue; } $newMessage = $this->makeXliffMessage($message); if ($message->getId() === $message->getSourceString()) { if (isset($englishCatalogue)) { try { $newMessage->setDesc($englishCatalogue->get($message->getId(), $message->getDomain())->getLocaleString()); } catch (InvalidArgumentException $e) { continue; } } else { $newMessage->setDesc($message->getLocaleString()); } } $newCatalogue->add($newMessage); } } $this->innerFileWriter->write($newCatalogue, $domain, $filePath, $format); }
public function extract() { $catalogue = new MessageCatalogue(); $collection = $this->router instanceof I18nRouter ? $this->router->getOriginalRouteCollection() : $this->router->getRouteCollection(); foreach ($collection->all() as $name => $route) { if ($this->routeExclusionStrategy->shouldExcludeRoute($name, $route)) { continue; } /////////////////////////////////////// // Begin customizations $meaning = "Route Controller and method: " . $route->getDefault('_controller'); // set a default value // prefix with zikula module url if requested if ($route->hasDefault('_zkModule')) { $zkNoBundlePrefix = $route->getOption('zkNoBundlePrefix'); if (!isset($zkNoBundlePrefix) || !$zkNoBundlePrefix) { $meaning = "This is a route from the " . $route->getDefault('_zkModule') . "Bundle and will include a translated prefix."; } } // End customizations /////////////////////////////////////// $message = new Message($name, $this->domain); $message->setDesc($route->getPath()); if (isset($meaning)) { $message->setMeaning($meaning); } $catalogue->add($message); } return $catalogue; }
public function testExtractConstraints() { $expected = new MessageCatalogue(); $path = __DIR__ . '/Fixture/MyFormModel.php'; $message = new Message('form.error.name_required', 'validators'); $expected->add($message); $this->assertEquals($expected, $this->extract('MyFormModel.php')); }
public function extract() { $catalogue = new MessageCatalogue(); $locationClass = new \ReflectionClass(Location::class); $sortConstants = array_filter($locationClass->getConstants(), function ($key) { return strtolower(substr($key, 0, 5)) === 'sort_'; }, ARRAY_FILTER_USE_KEY); foreach ($sortConstants as $sortId) { if (!isset($this->defaultTranslations[$sortId])) { continue; } $catalogue->add($this->createMessage('content_type.sort_field.' . $sortId, $this->defaultTranslations[$sortId], Location::class)); } $catalogue->add($this->createMessage('content_type.sort_order.0', 'Descending', Location::class)); $catalogue->add($this->createMessage('content_type.sort_order.1', 'Ascending', Location::class)); return $catalogue; }
public function extract() { $catalogue = new MessageCatalogue(); foreach ($this->fieldTypeCollectionFactory->getConcreteFieldTypesIdentifiers() as $fieldTypeIdentifier) { $catalogue->add(new Message($fieldTypeIdentifier . '.name', 'fieldtypes')); } return $catalogue; }
/** * @param mixed $resource * @param string $locale * @param string $domain * @return MessageCatalogue */ public function load($resource, $locale, $domain = 'messages') { $previous = libxml_use_internal_errors(true); if (false === ($doc = simplexml_load_file($resource))) { libxml_use_internal_errors($previous); $libxmlError = libxml_get_last_error(); throw new RuntimeException(sprintf('Could not load XML-file "%s": %s', $resource, $libxmlError->message)); } libxml_use_internal_errors($previous); $doc->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2'); $doc->registerXPathNamespace('jms', 'urn:jms:translation'); $hasReferenceFiles = in_array('urn:jms:translation', $doc->getNamespaces(true)); $catalogue = new MessageCatalogue(); $catalogue->setLocale($locale); /** @var \SimpleXMLElement $trans */ foreach ($doc->xpath('//xliff:trans-unit') as $trans) { $id = ($resName = (string) $trans->attributes()->resname) ? $resName : (string) $trans->source; /** @var Message $m */ $m = Message::create($id, $domain)->setDesc((string) $trans->source)->setLocaleString((string) $trans->target); $m->setApproved($trans['approved'] == 'yes'); if (isset($trans->target['state'])) { $m->setState((string) $trans->target['state']); } // Create closure $addNoteToMessage = function (Message $m, $note) { $m->addNote((string) $note, isset($note['from']) ? (string) $note['from'] : null); }; // If the translation has a note if (isset($trans->note)) { // If we have more than one note. We can't use is_array becuase $trans->note is a \SimpleXmlElement if (count($trans->note) > 1) { foreach ($trans->note as $note) { $addNoteToMessage($m, $note); } } else { $addNoteToMessage($m, $trans->note); } } $catalogue->add($m); if ($hasReferenceFiles) { foreach ($trans->xpath('./jms:reference-file') as $file) { $line = (string) $file->attributes()->line; $column = (string) $file->attributes()->column; $m->addSource(new FileSource((string) $file, $line ? (int) $line : null, $column ? (int) $column : null)); } } if ($meaning = (string) $trans->attributes()->extradata) { if (0 === strpos($meaning, 'Meaning: ')) { $meaning = substr($meaning, 9); } $m->setMeaning($meaning); } if (!($state = (string) $trans->target->attributes()->state) || 'new' !== $state) { $m->setNew(false); } } return $catalogue; }
public function testDumpStructureWithoutPrettyPrint() { $catalogue = new MessageCatalogue(); $catalogue->setLocale('fr'); $catalogue->add(new Message('foo.bar.baz')); $dumper = new PhpDumper(); $dumper->setPrettyPrint(false); $this->assertEquals($this->getOutput('structure_wo_pretty_print'), $dumper->dump($catalogue, 'messages')); }
/** * Converts Symfony's message catalogue to the catalogue of this * bundle. * * @param mixed $resource * @param string $locale * @param string $domain * @return MessageCatalogue */ public function load($resource, $locale, $domain = 'messages') { $catalogue = new MessageCatalogue(); $catalogue->setLocale($locale); foreach ($this->loader->load($resource, $locale, $domain)->all($domain) as $id => $message) { $catalogue->add(Message::create($id, $domain)->setLocaleString($message)->setNew(false)); } return $catalogue; }
/** * @param Node $node * @return void */ public function enterNode(Node $node) { if (!$node instanceof Node\Expr\MethodCall || !is_string($node->name) || !in_array(strtolower($node->name), array_map('strtolower', array_keys($this->methodsToExtractFrom)))) { $this->previousNode = $node; return; } $ignore = false; $desc = $meaning = null; if (null !== ($docComment = $this->getDocCommentForNode($node))) { if ($docComment instanceof Doc) { $docComment = $docComment->getText(); } foreach ($this->docParser->parse($docComment, 'file ' . $this->file . ' near line ' . $node->getLine()) as $annot) { if ($annot instanceof Ignore) { $ignore = true; } elseif ($annot instanceof Desc) { $desc = $annot->text; } elseif ($annot instanceof Meaning) { $meaning = $annot->text; } } } if (!$node->args[0]->value instanceof String_) { if ($ignore) { return; } $message = sprintf('Can only extract the translation id from a scalar string, but got "%s". Please refactor your code to make it extractable, or add the doc comment /** @Ignore */ to this code element (in %s on line %d).', get_class($node->args[0]->value), $this->file, $node->args[0]->value->getLine()); if ($this->logger) { $this->logger->error($message); return; } throw new RuntimeException($message); } $id = $node->args[0]->value->value; $index = $this->methodsToExtractFrom[strtolower($node->name)]; if (isset($node->args[$index])) { if (!$node->args[$index]->value instanceof String_) { if ($ignore) { return; } $message = sprintf('Can only extract the translation domain from a scalar string, but got "%s". Please refactor your code to make it extractable, or add the doc comment /** @Ignore */ to this code element (in %s on line %d).', get_class($node->args[0]->value), $this->file, $node->args[0]->value->getLine()); if ($this->logger) { $this->logger->error($message); return; } throw new RuntimeException($message); } $domain = $node->args[$index]->value->value; } else { $domain = 'messages'; } $message = new Message($id, $domain); $message->setDesc($desc); $message->setMeaning($meaning); $message->addSource($this->fileSourceFactory->create($this->file, $node->getLine())); $this->catalogue->add($message); }
/** * @param string $id * @param SourceInterface $source * @param string|null $domain */ private function addToCatalogue($id, SourceInterface $source, $domain = null) { if (null === $domain) { $message = new Message($id); } else { $message = new Message($id, $domain); } $message->addSource($source); $this->catalogue->add($message); }
public function extract() { $catalogue = new MessageCatalogue(); foreach ($this->i18nLoader->extract($this->router->getRouteCollection()) as $name => $route) { $message = new Message($name, $this->domain); $message->setDesc($route->getPattern()); $catalogue->add($message); } return $catalogue; }
public function testExtract() { $expected = new MessageCatalogue(); $path = __DIR__ . '/Fixture/MyFormType.php'; $message = new Message('bar'); $message->addSource(new FileSource($path, 36)); $expected->add($message); $message = new Message('form.states.empty_value'); $message->setDesc('Please select a state'); $message->addSource(new FileSource($path, 37)); $expected->add($message); $message = new Message('form.label.lastname'); $message->setDesc('Lastname'); $message->addSource(new FileSource($path, 33)); $expected->add($message); $message = new Message('form.label.firstname'); $message->addSource(new FileSource($path, 30)); $expected->add($message); $this->assertEquals($expected, $this->extract('MyFormType.php')); }
/** * @param Config $config */ private function setConfig(Config $config) { $this->config = $config; $this->logger->info(sprintf("Loading catalogues from \"%s\"", $config->getTranslationsDir())); $this->existingCatalogue = new MessageCatalogue(); // load external resources, so current translations can be reused in the final translation foreach ($config->getLoadResources() as $resource) { $this->existingCatalogue->merge($this->loader->loadFromDirectory($resource, $config->getLocale())); } $this->existingCatalogue->merge($this->loader->loadFromDirectory($config->getTranslationsDir(), $config->getLocale())); $this->extractor->reset(); $this->extractor->setDirectories($config->getScanDirs()); $this->extractor->setExcludedDirs($config->getExcludedDirs()); $this->extractor->setExcludedNames($config->getExcludedNames()); $this->extractor->setEnabledExtractors($config->getEnabledExtractors()); $this->logger->info("Extracting translation keys"); $this->scannedCatalogue = $this->extractor->extract(); $this->scannedCatalogue->setLocale($config->getLocale()); // merge existing messages into scanned messages foreach ($this->scannedCatalogue->getDomains() as $domainCatalogue) { foreach ($domainCatalogue->all() as $message) { if (!$this->existingCatalogue->has($message)) { continue; } $existingMessage = clone $this->existingCatalogue->get($message->getId(), $message->getDomain()); $existingMessage->mergeScanned($message); $this->scannedCatalogue->set($existingMessage, true); } } if ($this->config->isKeepOldMessages()) { foreach ($this->existingCatalogue->getDomains() as $domainCatalogue) { foreach ($domainCatalogue->all() as $message) { if ($this->scannedCatalogue->has($message)) { continue; } $this->scannedCatalogue->add($message); } } } //keep old translations translated if ($this->config->isKeepOldTranslationMessages()) { $locale = $this->scannedCatalogue->getLocale(); /** @var MessageCatalogue $domainCatalogue */ foreach ($this->scannedCatalogue->getDomains() as $domainCatalogue) { /** @var Message $message */ foreach ($domainCatalogue->all() as $message) { $translated = $this->translator->trans($message->getId(), array(), $message->getDomain(), $locale); $message->setLocaleString($translated); $message->setNew(false); } } } }
public function testOnlySomeExtractorsEnabled() { $foo = $this->getMock('JMS\\TranslationBundle\\Translation\\ExtractorInterface'); $foo->expects($this->never())->method('extract'); $catalogue = new MessageCatalogue(); $catalogue->add(new Message('foo')); $bar = $this->getMock('JMS\\TranslationBundle\\Translation\\ExtractorInterface'); $bar->expects($this->once())->method('extract')->will($this->returnValue($catalogue)); $manager = $this->getManager(null, array('foo' => $foo, 'bar' => $bar)); $manager->setEnabledExtractors(array('bar' => true)); $this->assertEquals($catalogue, $manager->extract()); }
public function extract() { $catalogue = new MessageCatalogue(); $collection = $this->router instanceof I18nRouter ? $this->router->getOriginalRouteCollection() : $this->router->getRouteCollection(); foreach ($collection->all() as $name => $route) { if ($this->routeExclusionStrategy->shouldExcludeRoute($name, $route)) { continue; } $message = new Message($name, $this->domain); $message->setDesc($route->getPath()); $catalogue->add($message); } return $catalogue; }
/** * @param string $id * @param string $source * @param null|string $domain * @param null|string $desc * @param null|string $meaning */ private function addToCatalogue($id, $source, $domain = null, $desc = null, $meaning = null) { if (null === $domain) { $message = new Message($id); } else { $message = new Message($id, $domain); } $message->addSource($source); if ($desc) { $message->setDesc($desc); } if ($meaning) { $message->setMeaning($meaning); } $this->catalogue->add($message); }
/** * @param Node $node */ public function enterNode(Node $node) { if (!$node instanceof Node\Expr\New_ || !is_string($node->class) || strtolower($node->class) !== 'validationerror') { $this->previousNode = $node; return; } $ignore = false; $desc = $meaning = null; if (null !== ($docComment = $this->getDocCommentForNode($node))) { if ($docComment instanceof Doc) { $docComment = $docComment->getText(); } foreach ($this->docParser->parse($docComment, 'file ' . $this->file . ' near line ' . $node->getLine()) as $annot) { if ($annot instanceof Ignore) { $ignore = true; } elseif ($annot instanceof Desc) { $desc = $annot->text; } elseif ($annot instanceof Meaning) { $meaning = $annot->text; } } } if (!$node->args[0]->value instanceof String_) { if ($ignore) { return; } $message = sprintf('Can only extract the translation id from a scalar string, but got "%s". Please refactor your code to make it extractable, or add the doc comment /** @Ignore */ to this code element (in %s on line %d).', get_class($node->args[0]->value), $this->file, $node->args[0]->value->getLine()); if ($this->logger) { $this->logger->error($message); return; } throw new RuntimeException($message); } $message = new Message($node->args[0]->value->value, $this->defaultDomain); $message->setDesc($desc); $message->setMeaning($meaning); $message->addSource($this->fileSourceFactory->create($this->file, $node->getLine())); $this->catalogue->add($message); // plural if ($node->args[1]->value instanceof String_) { $message = new Message($node->args[1]->value->value, $this->defaultDomain); $message->setDesc($desc); $message->setMeaning($meaning); $message->addSource($this->fileSourceFactory->create($this->file, $node->getLine())); $this->catalogue->add($message); } }