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; }
/** * @param Message $message * @return Boolean */ public function has(Message $message) { if (!$this->hasDomain($message->getDomain())) { return false; } return $this->getDomain($message->getDomain())->has($message->getId()); }
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 static function getTranslationMessages() { $messages = array(); foreach (self::$choices as $trans) { $message = new Message($trans); $message->addSource(new FileSource(__FILE__, 13)); $messages[] = $message; } return $messages; }
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 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 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 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 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; }
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 testGet() { $catalogue = new MessageCatalogue(); $catalogue->add($message = Message::create('foo')); $this->assertTrue($catalogue->hasDomain('messages')); $this->assertSame($message, $catalogue->get('foo')); }
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')); }
/** * 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; }
public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) { $this->stack[] = $node; if ($node instanceof \Twig_Node_Expression_Function) { $name = $node->getAttribute('name'); if (in_array($name, $this->methodNames)) { $args = $node->getNode('arguments'); switch ($name) { case '_n': case '_fn': $id = $args->getNode(0)->getAttribute('value') . '|' . $args->getNode(1)->getAttribute('value'); break; default: case '__f': case '__': $id = $args->getNode(0)->getAttribute('value'); break; } // obtain translation domain from composer file $composerPath = str_replace($this->file->getRelativePathname(), '', $this->file->getPathname()); if (isset(self::$domainCache[$composerPath])) { $domain = self::$domainCache[$composerPath]; } else { $scanner = new Scanner(); $scanner->scan(array($composerPath), 1); $metaData = $scanner->getModulesMetaData(true); $domains = array_keys($metaData); if (isset($domains[0])) { $domain = strtolower($domains[0]); // cache result of file lookup self::$domainCache[$composerPath] = $domain; } else { $domain = 'messages'; } } $domainNode = array_search($name, $this->methodNames); $domain = $args->hasNode($domainNode) ? $args->getNode($domainNode)->getAttribute('value') : $domain; $message = new Message($id, $domain); $message->addSource(new FileSource((string) $this->file, $node->getLine())); $this->catalogue->add($message); } } return $node; }
public function enterNode(\PHPParser_Node $node) { if (!$node instanceof \PHPParser_Node_Scalar_String) { return; } $id = $node->value; if (preg_match('/(\\.\\.|\\.\\.\\.)/', $id)) { return; } if (preg_match('/^http/', $id)) { return; } if (preg_match('/.*\\./', $id)) { $domain = 'messages'; $message = new Message($id, $domain); $message->addSource(new FileSource((string) $this->file, $node->getLine())); $this->catalogue->add($message); } }
public function testExtractWithSimpleTestFixtures() { $expected = array(); $basePath = __DIR__ . '/Fixture/SimpleTest/'; $fileSourceFactory = new FileSourceFactory('faux'); // Controller $message = new Message('controller.foo'); $message->addSource($fileSourceFactory->create(new \SplFileInfo($basePath . 'Controller/DefaultController.php'), 27)); $message->setDesc('Foo'); $expected['controller.foo'] = $message; // Form Model $expected['form.foo'] = new Message('form.foo'); $expected['form.bar'] = new Message('form.bar'); // Templates foreach (array('php', 'twig') as $engine) { $message = new Message($engine . '.foo'); $message->addSource($fileSourceFactory->create(new \SplFileInfo($basePath . 'Resources/views/' . $engine . '_template.html.' . $engine), 1)); $expected[$engine . '.foo'] = $message; $message = new Message($engine . '.bar'); $message->setDesc('Bar'); $message->addSource($fileSourceFactory->create(new \SplFileInfo($basePath . 'Resources/views/' . $engine . '_template.html.' . $engine), 3)); $expected[$engine . '.bar'] = $message; $message = new Message($engine . '.baz'); $message->setMeaning('Baz'); $message->addSource($fileSourceFactory->create(new \SplFileInfo($basePath . 'Resources/views/' . $engine . '_template.html.' . $engine), 5)); $expected[$engine . '.baz'] = $message; $message = new Message($engine . '.foo_bar'); $message->setDesc('Foo'); $message->setMeaning('Bar'); $message->addSource($fileSourceFactory->create(new \SplFileInfo($basePath . 'Resources/views/' . $engine . '_template.html.' . $engine), 7)); $expected[$engine . '.foo_bar'] = $message; } // File with global namespace. $message = new Message('globalnamespace.foo'); $message->addSource($fileSourceFactory->create(new \SplFileInfo($basePath . 'GlobalNamespace.php'), 27)); $message->setDesc('Bar'); $expected['globalnamespace.foo'] = $message; $actual = $this->extract(__DIR__ . '/Fixture/SimpleTest')->getDomain('messages')->all(); asort($expected); asort($actual); $this->assertEquals($expected, $actual); }
public function testLoadWithSymfonyFormat() { $loader = new XliffLoader(); $expected = new MessageCatalogue(); $expected->setLocale('en'); $expected->add(Message::create('foo1')->setDesc('foo1')->setLocaleString('bar')->setNew(false)); $expected->add(Message::create('foo2')->setDesc('foo2')->setLocaleString('bar')->setNew(false)); $expected->add(Message::create('foo3')->setDesc('foo3')->setLocaleString('bar')->setNew(false)); $expected->add(Message::create('foo4')->setDesc('foo4')->setLocaleString('bar')->setNew(false)); $this->assertEquals($expected, $loader->load(__DIR__ . '/Symfony/xliff/old_format.xml', 'en')); }
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')); }
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 visitPhpFile(\SplFileInfo $file, MessageCatalogue $catalogue, array $ast) { $this->catalogue = $catalogue; // Traverse document to assemble class name $traverser = new \PHPParser_NodeTraverser(); $traverser->addVisitor($this); $traverser->traverse($ast); if ($this->annotated) { // Get annotations for the class $annotationDriver = new Annotation(new DoctrineAnnotationReader()); $manager = new Manager(); $manager->addDriver($annotationDriver, -1); $metadata = $manager->getMetadata($this->parsedClassName); // Save messages for title foreach ($metadata->getFields() as $field) { $mappedField = $metadata->getFieldMapping($field); if ((!isset($mappedField['visible']) || $mappedField['visible']) && isset($mappedField['title'])) { $message = new Message($mappedField['title']); $message->addSource(new FileSource((string) $file)); $catalogue->add($message); } } } }
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); foreach ($doc->xpath('//xliff:trans-unit') as $trans) { $id = ($resName = (string) $trans->attributes()->resname) ? $resName : (string) $trans->source; $m = Message::create($id, $domain)->setDesc((string) $trans->source)->setLocaleString((string) $trans->target); $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 ? (integer) $line : null, // $column ? (integer) $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; }
/** * This test is used to check if translation from subscriber classes and even closures * are correctly extracted */ public function testExtractWithWithSubscriberAndListener() { $expected = new MessageCatalogue(); $path = __DIR__ . '/Fixture/MyFormTypeWithSubscriberAndListener.php'; $pathSubscriber = __DIR__ . '/Fixture/MyFormSubscriber.php'; $message = new Message('form.label.lastname'); $message->setDesc('Lastname'); $message->addSource(new FileSource($path, 36)); $expected->add($message); $message = new Message('form.label.firstname'); $message->addSource(new FileSource($path, 33)); $expected->add($message); $message = new Message('form.label.password'); $message->addSource(new FileSource($pathSubscriber, 37)); $expected->add($message); $message = new Message('form.label.password_repeated'); $message->setDesc('Repeat password'); $message->addSource(new FileSource($pathSubscriber, 40)); $expected->add($message); $message = new Message('form.label.zip', 'address'); $message->setDesc('ZIP'); $message->addSource(new FileSource($path, 51)); $expected->add($message); $message = new Message('form.error.password_mismatch', 'validators'); $message->setDesc('The entered passwords do not match'); $message->addSource(new FileSource($pathSubscriber, 42)); $expected->add($message); $catalogue = $this->extract('MyFormTypeWithSubscriberAndListener.php'); //Merge with the subscriber catalogue $catalogue->merge($this->extract('MyFormSubscriber.php')); $this->assertEquals($expected, $catalogue); }
public function enterNode(\PHPParser_Node $node) { if (!$node instanceof \PHPParser_Node_Expr_MethodCall || !is_string($node->name) || 'trans' !== strtolower($node->name) && 'transchoice' !== strtolower($node->name)) { $this->previousNode = $node; return; } $ignore = false; $desc = $meaning = null; if (null !== ($docComment = $this->getDocCommentForNode($node))) { foreach ($this->docParser->parse($docComment, 'file ' . $this->file . ' near line ' . $node->getLine()) as $annot) { if ($annot instanceof Ignore) { $ignore = true; } else { if ($annot instanceof Desc) { $desc = $annot->text; } else { if ($annot instanceof Meaning) { $meaning = $annot->text; } } } } } if ($ignore) { return; } if (!$node->args[0]->value instanceof \PHPParser_Node_Scalar_String) { $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->err($message); return; } throw new RuntimeException($message); } $id = $node->args[0]->value->value; $index = 'trans' === strtolower($node->name) ? 2 : 3; if (isset($node->args[$index])) { if (!$node->args[$index]->value instanceof \PHPParser_Node_Scalar_String) { $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->err($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(new FileSource((string) $this->file, $node->getLine())); $this->catalogue->add($message); }
/** * @param Node $node */ public function enterNode(Node $node) { if (!$node instanceof Node\Stmt\Throw_ || !$node->expr instanceof Node\Expr\New_) { $this->previousNode = $node; return; } $exceptionClass = $node->expr->class->parts[0]; if (!in_array(strtolower($exceptionClass), array_map('strtolower', $this->exceptionsToExtractFrom))) { $this->previousNode = $node; return; } $node = $node->expr; $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; $message = new Message($id, $this->defaultDomain); $message->setDesc($desc); $message->setMeaning($meaning); $message->addSource($this->fileSourceFactory->create($this->file, $node->getLine())); $this->catalogue->add($message); }
/** * @param string $id * @param string $domain */ private function addMessage($id, $domain) { $message = new Message($id, $domain); // $this->logger->debug(sprintf('extract: %s - domain:%s', $id, $domain)); $trace = debug_backtrace(false); if (isset($trace[1]['file'])) { $message->addSource(new FileSource($trace[1]['file'])); } $this->catalogue->add($message); }
/** * Get the catalogue used for the structure tests * * @return MessageCatalogue */ protected function getStructureCatalogue() { $catalogue = new MessageCatalogue(); $catalogue->setLocale('en'); $message = new Message('foo.bar.baz'); $message->addSource(new FileSource('/z/order/test', 1, 2)); $message->addSource(new FileSource('bar/baz', 1, 2)); $message->addSource(new FileSource('bar/baz', 1, 5)); $message->addSource(new FileSource('/a/b/c/foo/bar', 1, 2)); $catalogue->add($message); return $catalogue; }
public function testEmbeddedTemplate() { $expected = new MessageCatalogue(); $path = __DIR__ . '/Fixture/embedded_template.html.twig'; $message = new Message('foo'); $message->addSource(new FileSource($path, 3)); $expected->add($message); $this->assertEquals($expected, $this->extract('embedded_template.html.twig')); }
/** * @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); }
public function enterNode(\PHPParser_Node $node) { if ($node instanceof \PHPParser_Node_Stmt_Namespace) { $this->namespace = implode('\\', $node->name->parts); return; } if ($node instanceof \PHPParser_Node_Stmt_Class) { $name = '' === $this->namespace ? $node->name : $this->namespace . '\\' . $node->name; if (!class_exists($name)) { return; } $ref = new \ReflectionClass($name); if (!$ref->isSubclassOf('Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException') && $ref->name !== 'Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException') { return; } if (!$ref->hasMethod('getMessageKey')) { return; } $this->inAuthException = true; return; } if (!$this->inAuthException) { return; } if ($node instanceof \PHPParser_Node_Stmt_ClassMethod) { if ('getmessagekey' === strtolower($node->name)) { $this->inGetMessageKey = true; } return; } if (!$this->inGetMessageKey) { return; } if (!$node instanceof \PHPParser_Node_Stmt_Return) { return; } $ignore = false; $desc = $meaning = null; if ($docComment = $node->getDocComment()) { foreach ($this->docParser->parse($docComment->getText(), 'file ' . $this->file . ' near line ' . $node->getLine()) as $annot) { if ($annot instanceof Ignore) { $ignore = true; } else { if ($annot instanceof Desc) { $desc = $annot->text; } else { if ($annot instanceof Meaning) { $meaning = $annot->text; } } } } } if (!$node->expr instanceof \PHPParser_Node_Scalar_String) { if ($ignore) { return; } $message = sprintf('Could not extract id from return value, expected scalar string but got %s (in %s on line %d).', get_class($node->expr), $this->file, $node->expr->getLine()); if ($this->logger) { $this->logger->err($message); return; } throw new RuntimeException($message); } $message = Message::create($node->expr->value, $this->domain)->setDesc($desc)->setMeaning($meaning)->addSource(new FileSource((string) $this->file, $node->expr->getLine())); $this->catalogue->add($message); }