Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/bundle/Core/DependencyInjection/IbexaCoreExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -1024,10 +1024,10 @@ private function prependJMSTranslation(ContainerBuilder $container): void
'configs' => [
'ibexa_core' => [
'dirs' => [
__DIR__ . '/../',
__DIR__ . '/../../../',
],
'output_dir' => __DIR__ . '/../Resources/translations/',
'output_format' => 'xliff',
'output_format' => 'xlf',
'excluded_dirs' => ['Behat', 'Tests', 'node_modules', 'Features'],
],
],
Expand Down
4 changes: 2 additions & 2 deletions src/bundle/Core/Resources/translations/content_fields.en.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
<body>
<trans-unit id="f337a8fd9042dbc4de8b5d305b6d8df3c0c374c4" resname="content-field.latitude.not_set">
<source>Not set</source>
<target state="new">Not set</target>
<target>Not set</target>
<note>key: content-field.latitude.not_set</note>
</trans-unit>
<trans-unit id="687973ca20983f27a99c50243e364e346c9c4814" resname="content-field.longitude.not_set">
<source>Not set</source>
<target state="new">Not set</target>
<target>Not set</target>
<note>key: content-field.longitude.not_set</note>
</trans-unit>
</body>
Expand Down
115 changes: 19 additions & 96 deletions src/bundle/Core/Resources/translations/fielddefinition.en.xlf

Large diffs are not rendered by default.

Large diffs are not rendered by default.

8 changes: 1 addition & 7 deletions src/bundle/Core/Resources/translations/messages.en.xlf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?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 date="2017-01-26T14:55:58Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
<file source-language="en" target-language="en" 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>
Expand All @@ -10,32 +10,26 @@
<source>Enter login or email</source>
<target>Enter login or email</target>
<note>key: Enter login or email</note>
<jms:reference-file line="18">src/bundle/Core/Resources/views/Security/login.html.twig</jms:reference-file>
</trans-unit>
<trans-unit id="570591c060a999e9ab1592763c74d881b7654ee1" resname="Enter password">
<source>Enter password</source>
<target>Enter password</target>
<note>key: Enter password</note>
<jms:reference-file line="22">src/bundle/Core/Resources/views/Security/login.html.twig</jms:reference-file>
</trans-unit>
<trans-unit id="4e5a2893bdcc7d239c1db72e4c4ffbe4bea73174" resname="Login">
<source>Login</source>
<target>Login</target>
<note>key: Login</note>
<jms:reference-file line="32">src/bundle/Core/Resources/views/Security/login.html.twig</jms:reference-file>
<jms:reference-file line="6">src/bundle/Core/Resources/views/Security/login.html.twig</jms:reference-file>
</trans-unit>
<trans-unit id="be81ab98cb9ccf753975f50fa70cd32581a821fc" resname="Password:">
<source>Password:</source>
<target>Password:</target>
<note>key: Password:</note>
<jms:reference-file line="21">src/bundle/Core/Resources/views/Security/login.html.twig</jms:reference-file>
</trans-unit>
<trans-unit id="17dfb031e086e3415d71f3928e6ce08d6b1c1d4d" resname="Username:">
<source>Username:</source>
<target>Username:</target>
<note>key: Username:</note>
<jms:reference-file line="17">src/bundle/Core/Resources/views/Security/login.html.twig</jms:reference-file>
</trans-unit>
</body>
</file>
Expand Down
262 changes: 80 additions & 182 deletions src/bundle/Core/Resources/translations/repository_exceptions.en.xlf

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/lib/Base/Exceptions/ContentTypeValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Ibexa\Contracts\Core\Repository\Exceptions\ContentTypeValidationException as APIContentTypeValidationException;
use Ibexa\Core\Base\Translatable;
use Ibexa\Core\Base\TranslatableBase;
use JMS\TranslationBundle\Annotation\Ignore;

/**
* This Exception is thrown on create or update content type when content type is not valid.
Expand All @@ -25,8 +26,7 @@ class ContentTypeValidationException extends APIContentTypeValidationException i
*/
public function __construct($messageTemplate, array $parameters = [])
{
/** @Ignore */
$this->setMessageTemplate($messageTemplate);
$this->setMessageTemplate(/** @Ignore */$messageTemplate);
$this->setParameters($parameters);

parent::__construct($this->getBaseTranslation());
Expand Down
4 changes: 2 additions & 2 deletions src/lib/Base/Exceptions/ContentValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException as APIContentValidationException;
use Ibexa\Core\Base\Translatable;
use Ibexa\Core\Base\TranslatableBase;
use JMS\TranslationBundle\Annotation\Ignore;

/**
* This Exception is thrown on create or update content one or more given fields are not valid.
Expand All @@ -25,8 +26,7 @@ class ContentValidationException extends APIContentValidationException implement
*/
public function __construct($messageTemplate, array $parameters = [])
{
/** @Ignore */
$this->setMessageTemplate($messageTemplate);
$this->setMessageTemplate(/** @Ignore */$messageTemplate);
$this->setParameters($parameters);

parent::__construct($this->getBaseTranslation());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace Ibexa\Core\Helper\FieldsGroups;

use Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition;
use JMS\TranslationBundle\Annotation\Ignore;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
Expand Down Expand Up @@ -39,6 +40,7 @@ public function getGroups()

foreach ($this->groups as $groupIdentifier) {
$translatedGroups[$groupIdentifier] = $this->translator->trans(
/** @Ignore */
$groupIdentifier,
[],
'ezplatform_fields_groups'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface;
use Ibexa\Core\MVC\Symfony\Locale\LocaleConverterInterface;
use JMS\TranslationBundle\Annotation\Ignore;
use Locale;
use NumberFormatter;
use Symfony\Contracts\Translation\TranslatorInterface;
Expand Down Expand Up @@ -110,7 +111,9 @@ public function sizeFilter($number, $precision)
$i = ($index - 1);
}
$formatter = new NumberFormatter($this->getLocale(), NumberFormatter::PATTERN_DECIMAL);
$formatter->setPattern($formatter->getPattern() . ' ' . $this->translator->trans($this->suffixes[$i]));
$formatter->setPattern(
$formatter->getPattern() . ' ' . $this->translator->trans(/** @Ignore */$this->suffixes[$i])
);
$formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $precision);

return $formatter->format($number);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,126 @@
*/
namespace Ibexa\Core\MVC\Symfony\Translation;

use Doctrine\Common\Annotations\DocParser;
use JMS\TranslationBundle\Annotation\Ignore;
use JMS\TranslationBundle\Model\Message;
use JMS\TranslationBundle\Model\MessageCatalogue;
use JMS\TranslationBundle\Translation\Extractor\File\DefaultPhpFileExtractor;
use JMS\TranslationBundle\Translation\FileSourceFactory;
use PhpParser\Node;
use PhpParser\Node\Scalar\String_;
use PhpParser\NodeTraverser;
use Psr\Log\LoggerAwareTrait;
use SplFileInfo;

class ExceptionMessageTemplateFileVisitor extends DefaultPhpFileExtractor
{
protected $methodsToExtractFrom = ['setmessagetemplate' => -1];
use LoggerAwareTrait;

protected $defaultDomain = 'repository_exceptions';
/** @var array<string, int> */
protected $methodsToExtractFrom = ['setMessageTemplate' => -1];

protected string $defaultDomain = 'repository_exceptions';

private FileSourceFactory $fileSourceFactory;

private NodeTraverser $traverser;

private SplFileInfo $file;

private MessageCatalogue $catalogue;

private Node $previousNode;

private DocParser $docParser;

public function __construct(DocParser $docParser, FileSourceFactory $fileSourceFactory)
{
parent::__construct($docParser, $fileSourceFactory);
$this->fileSourceFactory = $fileSourceFactory;
$this->docParser = $docParser;
$this->traverser = new NodeTraverser();
$this->traverser->addVisitor($this);
}

public function enterNode(Node $node): void
{
$methodCallNodeName = null;
if ($node instanceof Node\Expr\MethodCall) {
$methodCallNodeName = $node->name instanceof Node\Identifier ? $node->name->name : $node->name;
}
if (
!is_string($methodCallNodeName)
|| !array_key_exists($methodCallNodeName, $this->methodsToExtractFrom)
) {
$this->previousNode = $node;

return;
}

$ignore = $this->isIgnore($node);

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());

$this->logger->error($message);

return;
}

$id = $node->args[0]->value->value;

$message = new Message($id, $this->defaultDomain);
$message->addSource($this->fileSourceFactory->create($this->file, $node->getLine()));
$this->catalogue->add($message);
}

public function visitPhpFile(SplFileInfo $file, MessageCatalogue $catalogue, array $ast): void
{
$this->file = $file;
$this->catalogue = $catalogue;
$this->traverser->traverse($ast);
}

private function getDocCommentForNode(Node $node): ?string
{
if (null !== $comment = $node->args[0]->getDocComment()) {
return $comment->getText();
}

if (null !== $comment = $node->getDocComment()) {
return $comment->getText();
}

if (null !== $this->previousNode && $this->previousNode->getDocComment() !== null) {
$comment = $this->previousNode->getDocComment();

return is_object($comment) ? $comment->getText() : $comment;
}

return null;
}

private function isIgnore($node): bool
{
if (null !== $docComment = $this->getDocCommentForNode($node)) {
$annotations = $this->docParser->parse(
$docComment,
'file ' . $this->file . ' near line ' . $node->getLine()
);
foreach ($annotations as $annot) {
if ($annot instanceof Ignore) {
return true;
}
}
}

return false;
}
}

class_alias(ExceptionMessageTemplateFileVisitor::class, 'eZ\Publish\Core\MVC\Symfony\Translation\ExceptionMessageTemplateFileVisitor');
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Tests\Core\MVC\Symfony\Translation;

use Doctrine\Common\Annotations\DocParser;
use Ibexa\Core\MVC\Symfony\Translation\ExceptionMessageTemplateFileVisitor;
use JMS\TranslationBundle\Model\Message;
use JMS\TranslationBundle\Model\MessageCatalogue;
use JMS\TranslationBundle\Translation\FileSourceFactory;
use PhpParser\Lexer;
use PhpParser\Parser;
use PhpParser\ParserFactory;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use SplFileInfo;

final class ExceptionMessageTemplateFileVisitorTest extends TestCase
{
private const FIXTURES_DIR = __DIR__ . '/fixtures/';

private Parser $phpParser;

private ExceptionMessageTemplateFileVisitor $exceptionMessageTemplateFileVisitor;

protected function setUp(): void
{
$docParser = new DocParser();
$fileSourceFactory = new FileSourceFactory(
self::FIXTURES_DIR,
);
$lexer = new Lexer();
$factory = new ParserFactory();
$this->phpParser = $factory->create(ParserFactory::PREFER_PHP7, $lexer);
$this->exceptionMessageTemplateFileVisitor = new ExceptionMessageTemplateFileVisitor(
$docParser,
$fileSourceFactory
);
}

public function testExtractTranslation(): void
{
$messageCatalogue = new MessageCatalogue();
$file = self::FIXTURES_DIR . 'SetMessageTemplate.php';
$fileInfo = new SplFileInfo($file);

$ast = $this->phpParser->parse(file_get_contents($file));
$this->exceptionMessageTemplateFileVisitor->visitPhpFile(
$fileInfo,
$messageCatalogue,
$ast
);

$expectedMessage = new Message('Foo exception', 'repository_exceptions');

self::assertTrue(
$messageCatalogue->has($expectedMessage)
);
}

public function testNoTranslationToExtract(): void
{
$messageCatalogue = new MessageCatalogue();
$file = self::FIXTURES_DIR . 'NoTranslationToExtract.php';
$fileInfo = new SplFileInfo($file);

$ast = $this->phpParser->parse(file_get_contents($file));
$this->exceptionMessageTemplateFileVisitor->visitPhpFile(
$fileInfo,
$messageCatalogue,
$ast
);

self::assertEmpty($messageCatalogue->getDomains());
}

public function testWrongTranslationId(): void
{
$messageCatalogue = new MessageCatalogue();
$file = self::FIXTURES_DIR . 'WrongTranslationId.php';
$fileInfo = new SplFileInfo($file);

$ast = $this->phpParser->parse(file_get_contents($file));

$logger = $this->createMock(LoggerInterface::class);
$logger
->expects($this->once())
->method('error');

$this->exceptionMessageTemplateFileVisitor->setLogger($logger);
$this->exceptionMessageTemplateFileVisitor->visitPhpFile(
$fileInfo,
$messageCatalogue,
$ast
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Tests\Core\MVC\Symfony\Translation\fixtures;

use Exception;
use Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException as APIInvalidArgumentException;
use Ibexa\Core\Base\Translatable;
use Ibexa\Core\Base\TranslatableBase;

final class NoTranslationToExtract extends APIInvalidArgumentException implements Translatable
{
use TranslatableBase;

public function __construct(?Exception $previous = null)
{
parent::__construct($this->getBaseTranslation(), 0, $previous);
}
}
Loading