Skip to content

Commit

Permalink
{_var} and {translate} can translate values during compile time
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed May 17, 2022
1 parent cef078a commit 2cbc947
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 7 deletions.
26 changes: 22 additions & 4 deletions src/Bridges/ApplicationLatte/Nodes/TranslateNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@

namespace Nette\Bridges\ApplicationLatte\Nodes;

use Latte\Compiler\NodeHelpers;
use Latte\Compiler\Nodes\AreaNode;
use Latte\Compiler\Nodes\NopNode;
use Latte\Compiler\Nodes\Php;
use Latte\Compiler\Nodes\Php\ModifierNode;
use Latte\Compiler\Nodes\StatementNode;
use Latte\Compiler\Nodes\TextNode;
use Latte\Compiler\PrintContext;
use Latte\Compiler\Tag;
use Latte\Helpers;
use Nette\Localization\Translator;


/**
Expand All @@ -29,7 +31,7 @@ class TranslateNode extends StatementNode


/** @return \Generator<int, ?array, array{AreaNode, ?Tag}, static|NopNode> */
public static function create(Tag $tag): \Generator
public static function create(Tag $tag, ?Translator $translator): \Generator
{
$tag->outputMode = $tag::OutputKeepIndentation;

Expand All @@ -42,22 +44,38 @@ public static function create(Tag $tag): \Generator
}

[$node->content] = yield;

if ($text = NodeHelpers::toText($node->content)) {
$node->content = new TextNode($text);
if ($translator) {
try {
$translation = $translator->translate($text, ...NodeHelpers::toValue($args, constants: true));
if (is_string($translation)) {
$node->content = new TextNode($translation);
return $node;
}
} catch (\InvalidArgumentException) {
}
}
}

array_unshift($node->modifier->filters, new Php\FilterNode(new Php\IdentifierNode('translate'), $args->toArguments()));

return $node;
}


public function print(PrintContext $context): string
{
if ($text = Helpers::toTextualContent($this->content)) {
if ($this->content instanceof TextNode) {
return $context->format(
<<<'XX'
$ʟ_fi = new LR\FilterInfo(%dump);
echo %modifyContent(%dump) %line;
XX,
$context->getEscaper()->export(),
$this->modifier,
$text,
$this->content->content,
$this->position,
);

Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/ApplicationLatte/Template.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public function addFunction(string $name, callable $callback)
* Sets translate adapter.
* @return static
*/
public function setTranslator(?Nette\Localization\Translator $translator)
public function setTranslator(?Nette\Localization\Translator $translator, ?string $language = null)
{
if (version_compare(Latte\Engine::VERSION, '3', '<')) {
$this->latte->addFilter(
Expand All @@ -117,7 +117,7 @@ function (Latte\Runtime\FilterInfo $fi, ...$args) use ($translator): string {
}
);
} else {
$this->latte->addExtension(new TranslatorExtension($translator));
$this->latte->addExtension(new TranslatorExtension($translator, $language));
}
return $this;
}
Expand Down
27 changes: 26 additions & 1 deletion src/Bridges/ApplicationLatte/TranslatorExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
namespace Nette\Bridges\ApplicationLatte;

use Latte;
use Latte\Compiler\NodeHelpers;
use Latte\Compiler\Nodes\Php;
use Latte\Compiler\Tag;
use Latte\Engine;
use Latte\Essential\Nodes\PrintNode;
use Nette\Localization\Translator;

Expand All @@ -23,6 +25,7 @@ final class TranslatorExtension extends Latte\Extension
{
public function __construct(
private ?Translator $translator,
private ?string $key = null,
) {
}

Expand All @@ -31,7 +34,7 @@ public function getTags(): array
{
return [
'_' => [$this, 'parseTranslate'],
'translate' => [Nodes\TranslateNode::class, 'create'],
'translate' => fn(Tag $tag): \Generator => Nodes\TranslateNode::create($tag, $this->key ? $this->translator : null),
];
}

Expand All @@ -46,6 +49,12 @@ public function getFilters(): array
}


public function getCacheKey(Engine $engine): mixed
{
return $this->key;
}


/**
* {_ ...}
*/
Expand All @@ -59,8 +68,24 @@ public function parseTranslate(Tag $tag): PrintNode
if ($tag->parser->stream->tryConsume(',')) {
$args = $tag->parser->parseArguments();
}

$node->modifier = $tag->parser->parseModifier();
$node->modifier->escape = true;

if ($this->translator && $this->key) {
try {
$translation = $this->translator->translate(
NodeHelpers::toValue($node->expression, constants: true),
...NodeHelpers::toValue($args, constants: true),
);
if (is_string($translation)) {
$node->expression = new Php\Scalar\StringNode($translation);
return $node;
}
} catch (\InvalidArgumentException) {
}
}

array_unshift($node->modifier->filters, new Php\FilterNode(new Php\IdentifierNode('translate'), $args->toArguments()));
return $node;
}
Expand Down
33 changes: 33 additions & 0 deletions tests/Bridges.Latte3/{_var}.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

declare(strict_types=1);

use Nette\Localization\Translator;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';
Expand Down Expand Up @@ -31,3 +32,35 @@ Assert::contains(
'echo LR\Filters::escapeHtmlText(($this->filters->translate)($var, 10, 20)) /* line 1 */;',
$latte->compile('{_$var, 10, 20}'),
);


class MyTranslator implements Translator
{
public function translate($message, ...$parameters): string
{
return strrev($message) . implode(',', $parameters);
}
}

$latte = new Latte\Engine;
$latte->setLoader(new Latte\Loaders\StringLoader);
$latte->addExtension(new Nette\Bridges\ApplicationLatte\TranslatorExtension(new MyTranslator));
Assert::contains(
'echo LR\Filters::escapeHtmlText(($this->filters->translate)(\'a&b\', 1, 2))',
$latte->compile('{_"a&b", 1, 2}'),
);
Assert::same(
'b&amp;a1,2',
$latte->renderToString('{_"a&b", 1, 2}'),
);


$latte->addExtension(new Nette\Bridges\ApplicationLatte\TranslatorExtension(new MyTranslator, 'en'));
Assert::contains(
'echo LR\Filters::escapeHtmlText(\'b&a1,2\')',
$latte->compile('{_"a&b", 1, 2}'),
);
Assert::same(
'b&amp;a1,2',
$latte->renderToString('{_"a&b", 1, 2}'),
);
33 changes: 33 additions & 0 deletions tests/Bridges.Latte3/{translate}.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

declare(strict_types=1);

use Nette\Localization\Translator;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';
Expand Down Expand Up @@ -65,3 +66,35 @@ Assert::notContains(
"'translate'",
$latte->compile('{translate /}'),
);


class MyTranslator implements Translator
{
public function translate($message, ...$parameters): string
{
return strrev($message) . implode(',', $parameters);
}
}

$latte = new Latte\Engine;
$latte->setLoader(new Latte\Loaders\StringLoader);
$latte->addExtension(new Nette\Bridges\ApplicationLatte\TranslatorExtension(new MyTranslator));
Assert::contains(
'echo LR\Filters::convertTo($ʟ_fi, \'html\', $this->filters->filterContent(\'translate\', $ʟ_fi, \'a&b\', 1, 2))',
$latte->compile('{translate 1,2}a&b{/translate}'),
);
Assert::same(
'b&a1,2',
$latte->renderToString('{translate 1,2}a&b{/translate}'),
);


$latte->addExtension(new Nette\Bridges\ApplicationLatte\TranslatorExtension(new MyTranslator, 'en'));
Assert::contains(
'echo LR\Filters::convertTo($ʟ_fi, \'html\', \'b&a1,2\')',
$latte->compile('{translate 1,2}a&b{/translate}'),
);
Assert::same(
'b&a1,2',
$latte->renderToString('{translate 1,2}a&b{/translate}'),
);

0 comments on commit 2cbc947

Please sign in to comment.