From f46f5956c822e910a85ec7edafa8c606f184fb35 Mon Sep 17 00:00:00 2001 From: mscherer Date: Sat, 7 Jun 2025 11:38:52 +0200 Subject: [PATCH 1/3] Allow using __d() in plugin context. --- src/Command/TemplateCommand.php | 9 ++++ templates/bake/Template/index.twig | 24 +++++------ templates/bake/Template/login.twig | 4 +- templates/bake/Template/view.twig | 42 +++++++++---------- .../TestCase/Command/TemplateCommandTest.php | 22 ++++++++++ 5 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/Command/TemplateCommand.php b/src/Command/TemplateCommand.php index 558187ab9..b055b5407 100644 --- a/src/Command/TemplateCommand.php +++ b/src/Command/TemplateCommand.php @@ -406,6 +406,12 @@ public function getContent(Arguments $args, ConsoleIo $io, string $action, ?arra } $renderer->set('indexColumns', $indexColumns); + $useDomain = $args->getOption('use-domain') ?? false; + if (!$this->plugin) { + throw new RuntimeException('Cannot set useDomain option when not in a plugin context.'); + } + $renderer->set('useDomain', $useDomain); + return $renderer->generate("Bake.Template/$action"); } @@ -431,6 +437,9 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar 'help' => 'The controller name if you have a controller that does not follow conventions.', ])->addOption('prefix', [ 'help' => 'The routing prefix to generate views for.', + ])->addOption('use-domain', [ + 'help' => 'Use __d() instead of __() for translations.', + 'boolean' => true, ])->addOption('index-columns', [ 'help' => 'Limit for the number of index columns', 'default' => '0', diff --git a/templates/bake/Template/index.twig b/templates/bake/Template/index.twig index 7cab8aa11..d3fbbabca 100644 --- a/templates/bake/Template/index.twig +++ b/templates/bake/Template/index.twig @@ -21,9 +21,9 @@ ?>
{% set fields = Bake.filterFields(fields, schema, modelObject, indexColumns, ['binary', 'text']) %} - Html->link(__('New {{ singularHumanName }}'), ['action' => 'add'], ['class' => 'button float-right']) ?> + Html->link({% if useDomain %}__d('{{ plugin }}', {% else %}{% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}{% endif %}'New {{ singularHumanName }}'), ['action' => 'add'], ['class' => 'button float-right']) ?> {% set done = [] %} -

+

@@ -31,7 +31,7 @@ {% for field in fields %} {% endfor %} - + @@ -63,14 +63,14 @@ {% endfor %} {% set pk = '$' ~ singularVar ~ '->' ~ primaryKey[0] %} @@ -81,12 +81,12 @@
    - Paginator->first('<< ' . __('first')) ?> - Paginator->prev('< ' . __('previous')) ?> + Paginator->first('<< ' . {% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'first')) ?> + Paginator->prev('< ' . {% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'previous')) ?> Paginator->numbers() ?> - Paginator->next(__('next') . ' >') ?> - Paginator->last(__('last') . ' >>') ?> + Paginator->next({% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'next') . ' >') ?> + Paginator->last({% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'last') . ' >>') ?>
-

Paginator->counter(__('Page {{ '{{' }}page{{ '}}' }} of {{ '{{' }}pages{{ '}}' }}, showing {{ '{{' }}current{{ '}}' }} record(s) out of {{ '{{' }}count{{ '}}' }} total')) ?>

+

Paginator->counter({% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'Page {{ '{{' }}page{{ '}}' }} of {{ '{{' }}pages{{ '}}' }}, showing {{ '{{' }}current{{ '}}' }} record(s) out of {{ '{{' }}count{{ '}}' }} total')) ?>

\ No newline at end of file diff --git a/templates/bake/Template/login.twig b/templates/bake/Template/login.twig index 77f14d1cc..8f50536cb 100644 --- a/templates/bake/Template/login.twig +++ b/templates/bake/Template/login.twig @@ -21,10 +21,10 @@
Form->create() ?>
- + Form->control('username') ?> Form->control('password') ?>
- Form->button(__('Login')); ?> + Form->button({% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'Login')); ?> Form->end() ?>
diff --git a/templates/bake/Template/view.twig b/templates/bake/Template/view.twig index de4141355..71ddc2daf 100644 --- a/templates/bake/Template/view.twig +++ b/templates/bake/Template/view.twig @@ -27,11 +27,11 @@
@@ -44,12 +44,12 @@ {% if associationFields[field] is defined %} {% set details = associationFields[field] %}
- + {% else %} - + {% endif %} @@ -58,7 +58,7 @@ {% if associations.HasOne %} {% for alias, details in associations.HasOne %} - + {% endfor %} @@ -66,7 +66,7 @@ {% if groupedFields.number %} {% for field in groupedFields.number %} - + {% set columnData = Bake.columnData(field, schema) %} {% if columnData.null %} @@ -79,7 +79,7 @@ {% if groupedFields.enum %} {% for field in groupedFields.enum %} - + {% set columnData = Bake.columnData(field, schema) %} {% set supportsLabel = Bake.enumSupportsLabel(field, schema) %} {% if columnData.null %} @@ -93,7 +93,7 @@ {% if groupedFields.date %} {% for field in groupedFields.date %} - + {% endfor %} @@ -101,8 +101,8 @@ {% if groupedFields.boolean %} {% for field in groupedFields.boolean %} - - + + {% endfor %} {% endif %} @@ -110,7 +110,7 @@ {% if groupedFields.text %} {% for field in groupedFields.text %}
- +
Text->autoParagraph(h(${{ singularVar }}->{{ field }})); ?>
@@ -122,15 +122,15 @@ {% set otherSingularVar = alias|singularize|variable %} {% set otherPluralHumanName = details.controller|underscore|humanize %}
Paginator->sort('{{ field }}') ?>
- Html->link(__('View'), ['action' => 'view', {{ pk|raw }}]) ?> - Html->link(__('Edit'), ['action' => 'edit', {{ pk|raw }}]) ?> + Html->link({% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'View'), ['action' => 'view', {{ pk|raw }}]) ?> + Html->link({% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'Edit'), ['action' => 'edit', {{ pk|raw }}]) ?> Form->postLink( - __('Delete'), + {% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'Delete'), ['action' => 'delete', {{ pk|raw }}], [ 'method' => 'delete', - 'confirm' => __('Are you sure you want to delete # {0}?', {{ pk|raw }}), + 'confirm' => {% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'Are you sure you want to delete # {0}?', {{ pk|raw }}), ] ) ?>
hasValue('{{ details.property }}') ? $this->Html->link(${{ singularVar }}->{{ details.property }}->{{ details.displayField }}, ['controller' => '{{ details.controller }}', 'action' => 'view', ${{ singularVar }}->{{ details.property }}->{{ details.primaryKey[0] }}]) : '' ?>
{{ field }}) ?>
hasValue('{{ details.property }}') ? $this->Html->link(${{ singularVar }}->{{ details.property }}->{{ details.displayField }}, ['controller' => '{{ details.controller }}', 'action' => 'view', ${{ singularVar }}->{{ details.property }}->{{ details.primaryKey[0] }}]) : '' ?>
{{ field }} === null ? '' : $this->Number->format(${{ singularVar }}->{{ field }}) ?>
{{ field }}) ?>
{{ field }} ? __('Yes') : __('No'); ?>{{ field }} ? {% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'Yes') : {% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'No'); ?>
{% for field in details.fields %} - + {% endfor %} - + {{ details.property }} as ${{ otherSingularVar }}) : ?> @@ -139,14 +139,14 @@ {% endfor %} {% set otherPk = '$' ~ otherSingularVar ~ '->' ~ details.primaryKey[0] %} diff --git a/tests/TestCase/Command/TemplateCommandTest.php b/tests/TestCase/Command/TemplateCommandTest.php index cd99d0bba..5496e3ea7 100644 --- a/tests/TestCase/Command/TemplateCommandTest.php +++ b/tests/TestCase/Command/TemplateCommandTest.php @@ -659,6 +659,28 @@ public function testBakeIndexPlugin() $this->assertFileContains('$comment->article->id', $this->generatedFile); } + /** + * test Bake with plugins with __d() translations. + * + * @return void + */ + public function testBakePluginTemplatesWithDomain() + { + $this->_loadTestPlugin('BakeTest'); + $path = Plugin::templatePath('BakeTest'); + + // Setup association to ensure properties don't have dots + $model = $this->getTableLocator()->get('BakeTest.Comments'); + $model->belongsTo('Articles'); + + $this->generatedFile = $path . 'Comments/index.php'; + $this->exec('bake template BakeTest.comments index --use-domain'); + + $this->assertExitCode(CommandInterface::CODE_SUCCESS); + $this->assertFileExists($this->generatedFile); + $this->assertFileContains('__d(\'BakeTest\', ', $this->generatedFile); + } + /** * Ensure that models in a tree don't include form fields for lft/rght * From a7722e246547c3fa0358e0e11972055e1645c0f6 Mon Sep 17 00:00:00 2001 From: mscherer Date: Sat, 7 Jun 2025 11:50:12 +0200 Subject: [PATCH 2/3] Allow using __d() in plugin context. --- src/Command/TemplateCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Command/TemplateCommand.php b/src/Command/TemplateCommand.php index b055b5407..c85036167 100644 --- a/src/Command/TemplateCommand.php +++ b/src/Command/TemplateCommand.php @@ -407,7 +407,7 @@ public function getContent(Arguments $args, ConsoleIo $io, string $action, ?arra $renderer->set('indexColumns', $indexColumns); $useDomain = $args->getOption('use-domain') ?? false; - if (!$this->plugin) { + if ($useDomain && !$this->plugin) { throw new RuntimeException('Cannot set useDomain option when not in a plugin context.'); } $renderer->set('useDomain', $useDomain); From 685989e57946e1892ecb59f13b63ad7194094334 Mon Sep 17 00:00:00 2001 From: mscherer Date: Mon, 29 Sep 2025 17:31:20 +0200 Subject: [PATCH 3/3] Simplify approach. --- src/Command/ControllerCommand.php | 11 ++++++----- src/Command/TemplateCommand.php | 9 ++------- templates/bake/Template/index.twig | 2 +- templates/bake/element/Controller/add.twig | 4 ++-- templates/bake/element/Controller/delete.twig | 4 ++-- templates/bake/element/Controller/edit.twig | 4 ++-- templates/bake/element/Controller/login.twig | 4 ++-- tests/TestCase/Command/TemplateCommandTest.php | 2 +- tests/comparisons/Controller/testBakeWithPlugin.php | 12 ++++++------ 9 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/Command/ControllerCommand.php b/src/Command/ControllerCommand.php index c78bc5df4..faa19f2cf 100644 --- a/src/Command/ControllerCommand.php +++ b/src/Command/ControllerCommand.php @@ -112,14 +112,15 @@ public function bake(string $controllerName, Arguments $args, ConsoleIo $io): vo $currentModelName = $controllerName; $plugin = $this->plugin; - if ($plugin) { - $plugin .= '.'; + $pluginPath = $plugin; + if ($pluginPath) { + $pluginPath .= '.'; } - if ($this->getTableLocator()->exists($plugin . $currentModelName)) { - $modelObj = $this->getTableLocator()->get($plugin . $currentModelName); + if ($this->getTableLocator()->exists($pluginPath . $currentModelName)) { + $modelObj = $this->getTableLocator()->get($pluginPath . $currentModelName); } else { - $modelObj = $this->getTableLocator()->get($plugin . $currentModelName, [ + $modelObj = $this->getTableLocator()->get($pluginPath . $currentModelName, [ 'connectionName' => $this->connection, ]); } diff --git a/src/Command/TemplateCommand.php b/src/Command/TemplateCommand.php index d23064b45..8edd388a5 100644 --- a/src/Command/TemplateCommand.php +++ b/src/Command/TemplateCommand.php @@ -408,10 +408,8 @@ public function getContent(Arguments $args, ConsoleIo $io, string $action, ?arra } $renderer->set('indexColumns', $indexColumns); - $useDomain = $args->getOption('use-domain') ?? false; - if ($useDomain && !$this->plugin) { - throw new RuntimeException('Cannot set useDomain option when not in a plugin context.'); - } + // Always use domain translations when in plugin context + $useDomain = (bool)$this->plugin; $renderer->set('useDomain', $useDomain); return $renderer->generate("Bake.Template/$action"); @@ -439,9 +437,6 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar 'help' => 'The controller name if you have a controller that does not follow conventions.', ])->addOption('prefix', [ 'help' => 'The routing prefix to generate views for.', - ])->addOption('use-domain', [ - 'help' => 'Use __d() instead of __() for translations.', - 'boolean' => true, ])->addOption('index-columns', [ 'help' => 'Limit for the number of index columns', 'default' => '0', diff --git a/templates/bake/Template/index.twig b/templates/bake/Template/index.twig index d3fbbabca..b7d95f453 100644 --- a/templates/bake/Template/index.twig +++ b/templates/bake/Template/index.twig @@ -21,7 +21,7 @@ ?>
{% set fields = Bake.filterFields(fields, schema, modelObject, indexColumns, ['binary', 'text']) %} - Html->link({% if useDomain %}__d('{{ plugin }}', {% else %}{% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}{% endif %}'New {{ singularHumanName }}'), ['action' => 'add'], ['class' => 'button float-right']) ?> + Html->link({% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'New {{ singularHumanName }}'), ['action' => 'add'], ['class' => 'button float-right']) ?> {% set done = [] %}

diff --git a/templates/bake/element/Controller/add.twig b/templates/bake/element/Controller/add.twig index 081d1c79f..7b0065bc5 100644 --- a/templates/bake/element/Controller/add.twig +++ b/templates/bake/element/Controller/add.twig @@ -28,11 +28,11 @@ if ($this->request->is('post')) { ${{ singularName }} = $this->{{ currentModelName }}->patchEntity(${{ singularName }}, $this->request->getData()); if ($this->{{ currentModelName }}->save(${{ singularName }})) { - $this->Flash->success(__('The {{ singularHumanName|lower }} has been saved.')); + $this->Flash->success({% if plugin %}__d('{{ plugin }}', {% else %}__({% endif %}'The {{ singularHumanName|lower }} has been saved.')); return $this->redirect(['action' => 'index']); } - $this->Flash->error(__('The {{ singularHumanName|lower }} could not be saved. Please, try again.')); + $this->Flash->error({% if plugin %}__d('{{ plugin }}', {% else %}__({% endif %}'The {{ singularHumanName|lower }} could not be saved. Please, try again.')); } {% set associations = Bake.aliasExtractor(modelObj, 'BelongsTo') %} {% set associations = associations|merge(Bake.aliasExtractor(modelObj, 'BelongsToMany')) %} diff --git a/templates/bake/element/Controller/delete.twig b/templates/bake/element/Controller/delete.twig index bab93c72a..70be262f1 100644 --- a/templates/bake/element/Controller/delete.twig +++ b/templates/bake/element/Controller/delete.twig @@ -28,9 +28,9 @@ $this->Authorization->authorize(${{ singularName }}); {% endif %} if ($this->{{ currentModelName }}->delete(${{ singularName }})) { - $this->Flash->success(__('The {{ singularHumanName|lower }} has been deleted.')); + $this->Flash->success({% if plugin %}__d('{{ plugin }}', {% else %}__({% endif %}'The {{ singularHumanName|lower }} has been deleted.')); } else { - $this->Flash->error(__('The {{ singularHumanName|lower }} could not be deleted. Please, try again.')); + $this->Flash->error({% if plugin %}__d('{{ plugin }}', {% else %}__({% endif %}'The {{ singularHumanName|lower }} could not be deleted. Please, try again.')); } return $this->redirect(['action' => 'index']); diff --git a/templates/bake/element/Controller/edit.twig b/templates/bake/element/Controller/edit.twig index 793f8515f..6abd4c4de 100644 --- a/templates/bake/element/Controller/edit.twig +++ b/templates/bake/element/Controller/edit.twig @@ -32,11 +32,11 @@ if ($this->request->is(['patch', 'post', 'put'])) { ${{ singularName }} = $this->{{ currentModelName }}->patchEntity(${{ singularName }}, $this->request->getData()); if ($this->{{ currentModelName }}->save(${{ singularName }})) { - $this->Flash->success(__('The {{ singularHumanName|lower }} has been saved.')); + $this->Flash->success({% if plugin %}__d('{{ plugin }}', {% else %}__({% endif %}'The {{ singularHumanName|lower }} has been saved.')); return $this->redirect(['action' => 'index']); } - $this->Flash->error(__('The {{ singularHumanName|lower }} could not be saved. Please, try again.')); + $this->Flash->error({% if plugin %}__d('{{ plugin }}', {% else %}__({% endif %}'The {{ singularHumanName|lower }} could not be saved. Please, try again.')); } {% for assoc in belongsTo|merge(belongsToMany) %} {%- set otherName = Bake.getAssociatedTableAlias(modelObj, assoc) %} diff --git a/templates/bake/element/Controller/login.twig b/templates/bake/element/Controller/login.twig index 409f02433..84e116246 100644 --- a/templates/bake/element/Controller/login.twig +++ b/templates/bake/element/Controller/login.twig @@ -27,7 +27,7 @@ $this->request->allowMethod(['get', 'post']); $result = $this->Authentication->getResult(); if ($result->isValid()) { - $this->Flash->success(__('Login successful')); + $this->Flash->success({% if plugin %}__d('{{ plugin }}', {% else %}__({% endif %}'Login successful')); $redirect = $this->Authentication->getLoginRedirect(); if ($redirect) { return $this->redirect($redirect); @@ -36,6 +36,6 @@ // Display error if user submitted and authentication failed if ($this->request->is('post')) { - $this->Flash->error(__('Invalid username or password')); + $this->Flash->error({% if plugin %}__d('{{ plugin }}', {% else %}__({% endif %}'Invalid username or password')); } } diff --git a/tests/TestCase/Command/TemplateCommandTest.php b/tests/TestCase/Command/TemplateCommandTest.php index 5496e3ea7..14bb723f5 100644 --- a/tests/TestCase/Command/TemplateCommandTest.php +++ b/tests/TestCase/Command/TemplateCommandTest.php @@ -674,7 +674,7 @@ public function testBakePluginTemplatesWithDomain() $model->belongsTo('Articles'); $this->generatedFile = $path . 'Comments/index.php'; - $this->exec('bake template BakeTest.comments index --use-domain'); + $this->exec('bake template BakeTest.comments index'); $this->assertExitCode(CommandInterface::CODE_SUCCESS); $this->assertFileExists($this->generatedFile); diff --git a/tests/comparisons/Controller/testBakeWithPlugin.php b/tests/comparisons/Controller/testBakeWithPlugin.php index fb16c6e76..a3f091547 100644 --- a/tests/comparisons/Controller/testBakeWithPlugin.php +++ b/tests/comparisons/Controller/testBakeWithPlugin.php @@ -50,11 +50,11 @@ public function add() if ($this->request->is('post')) { $bakeArticle = $this->BakeArticles->patchEntity($bakeArticle, $this->request->getData()); if ($this->BakeArticles->save($bakeArticle)) { - $this->Flash->success(__('The bake article has been saved.')); + $this->Flash->success(__d('BakeTest', 'The bake article has been saved.')); return $this->redirect(['action' => 'index']); } - $this->Flash->error(__('The bake article could not be saved. Please, try again.')); + $this->Flash->error(__d('BakeTest', 'The bake article could not be saved. Please, try again.')); } $bakeUsers = $this->BakeArticles->BakeUsers->find('list', limit: 200)->all(); $bakeTags = $this->BakeArticles->BakeTags->find('list', limit: 200)->all(); @@ -74,11 +74,11 @@ public function edit($id = null) if ($this->request->is(['patch', 'post', 'put'])) { $bakeArticle = $this->BakeArticles->patchEntity($bakeArticle, $this->request->getData()); if ($this->BakeArticles->save($bakeArticle)) { - $this->Flash->success(__('The bake article has been saved.')); + $this->Flash->success(__d('BakeTest', 'The bake article has been saved.')); return $this->redirect(['action' => 'index']); } - $this->Flash->error(__('The bake article could not be saved. Please, try again.')); + $this->Flash->error(__d('BakeTest', 'The bake article could not be saved. Please, try again.')); } $bakeUsers = $this->BakeArticles->BakeUsers->find('list', limit: 200)->all(); $bakeTags = $this->BakeArticles->BakeTags->find('list', limit: 200)->all(); @@ -97,9 +97,9 @@ public function delete($id = null) $this->request->allowMethod(['post', 'delete']); $bakeArticle = $this->BakeArticles->get($id); if ($this->BakeArticles->delete($bakeArticle)) { - $this->Flash->success(__('The bake article has been deleted.')); + $this->Flash->success(__d('BakeTest', 'The bake article has been deleted.')); } else { - $this->Flash->error(__('The bake article could not be deleted. Please, try again.')); + $this->Flash->error(__d('BakeTest', 'The bake article could not be deleted. Please, try again.')); } return $this->redirect(['action' => 'index']);
- Html->link(__('View'), ['controller' => '{{ details.controller }}', 'action' => 'view', {{ otherPk|raw }}]) ?> - Html->link(__('Edit'), ['controller' => '{{ details.controller }}', 'action' => 'edit', {{ otherPk|raw }}]) ?> + Html->link({% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'View'), ['controller' => '{{ details.controller }}', 'action' => 'view', {{ otherPk|raw }}]) ?> + Html->link({% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'Edit'), ['controller' => '{{ details.controller }}', 'action' => 'edit', {{ otherPk|raw }}]) ?> Form->postLink( - __('Delete'), + {% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'Delete'), ['controller' => '{{ details.controller }}', 'action' => 'delete', {{ otherPk|raw }}], [ 'method' => 'delete', - 'confirm' => __('Are you sure you want to delete # {0}?', {{ otherPk|raw }}), + 'confirm' => {% if useDomain %}__d('{{ plugin }}', {% else %}__({% endif %}'Are you sure you want to delete # {0}?', {{ otherPk|raw }}), ] ) ?>