Skip to content

Commit d912384

Browse files
alexander-schranzfabpot
authored andcommitted
[Mime] Add TemplatedEmail::locale() to set the locale for the email rendering
1 parent 9778b08 commit d912384

File tree

7 files changed

+80
-23
lines changed

7 files changed

+80
-23
lines changed

src/Symfony/Bridge/Twig/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ CHANGELOG
44
6.4
55
---
66

7-
* Allow an array to be passed as the first argument to the `importmap()` Twig function
7+
* Allow an array to be passed as the first argument to the `importmap()` Twig function
8+
* Add `TemplatedEmail::locale()` to set the locale for the email rendering
89

910
6.3
1011
---

src/Symfony/Bridge/Twig/Mime/BodyRenderer.php

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Component\Mime\HtmlToTextConverter\HtmlToTextConverterInterface;
1919
use Symfony\Component\Mime\HtmlToTextConverter\LeagueHtmlToMarkdownConverter;
2020
use Symfony\Component\Mime\Message;
21+
use Symfony\Component\Translation\LocaleSwitcher;
2122
use Twig\Environment;
2223

2324
/**
@@ -28,12 +29,14 @@ final class BodyRenderer implements BodyRendererInterface
2829
private Environment $twig;
2930
private array $context;
3031
private HtmlToTextConverterInterface $converter;
32+
private ?LocaleSwitcher $localeSwitcher = null;
3133

32-
public function __construct(Environment $twig, array $context = [], HtmlToTextConverterInterface $converter = null)
34+
public function __construct(Environment $twig, array $context = [], HtmlToTextConverterInterface $converter = null, LocaleSwitcher $localeSwitcher = null)
3335
{
3436
$this->twig = $twig;
3537
$this->context = $context;
3638
$this->converter = $converter ?: (interface_exists(HtmlConverterInterface::class) ? new LeagueHtmlToMarkdownConverter() : new DefaultHtmlToTextConverter());
39+
$this->localeSwitcher = $localeSwitcher;
3740
}
3841

3942
public function render(Message $message): void
@@ -47,30 +50,42 @@ public function render(Message $message): void
4750
return;
4851
}
4952

50-
$messageContext = $message->getContext();
53+
$callback = function () use ($message) {
54+
$messageContext = $message->getContext();
5155

52-
if (isset($messageContext['email'])) {
53-
throw new InvalidArgumentException(sprintf('A "%s" context cannot have an "email" entry as this is a reserved variable.', get_debug_type($message)));
54-
}
56+
if (isset($messageContext['email'])) {
57+
throw new InvalidArgumentException(sprintf('A "%s" context cannot have an "email" entry as this is a reserved variable.', get_debug_type($message)));
58+
}
5559

56-
$vars = array_merge($this->context, $messageContext, [
57-
'email' => new WrappedTemplatedEmail($this->twig, $message),
58-
]);
60+
$vars = array_merge($this->context, $messageContext, [
61+
'email' => new WrappedTemplatedEmail($this->twig, $message),
62+
]);
5963

60-
if ($template = $message->getTextTemplate()) {
61-
$message->text($this->twig->render($template, $vars));
62-
}
64+
if ($template = $message->getTextTemplate()) {
65+
$message->text($this->twig->render($template, $vars));
66+
}
6367

64-
if ($template = $message->getHtmlTemplate()) {
65-
$message->html($this->twig->render($template, $vars));
66-
}
68+
if ($template = $message->getHtmlTemplate()) {
69+
$message->html($this->twig->render($template, $vars));
70+
}
71+
72+
$message->markAsRendered();
6773

68-
$message->markAsRendered();
74+
// if text body is empty, compute one from the HTML body
75+
if (!$message->getTextBody() && null !== $html = $message->getHtmlBody()) {
76+
$text = $this->converter->convert(\is_resource($html) ? stream_get_contents($html) : $html, $message->getHtmlCharset());
77+
$message->text($text, $message->getHtmlCharset());
78+
}
79+
};
6980

70-
// if text body is empty, compute one from the HTML body
71-
if (!$message->getTextBody() && null !== $html = $message->getHtmlBody()) {
72-
$text = $this->converter->convert(\is_resource($html) ? stream_get_contents($html) : $html, $message->getHtmlCharset());
73-
$message->text($text, $message->getHtmlCharset());
81+
$locale = $message->getLocale();
82+
83+
if ($locale && $this->localeSwitcher) {
84+
$this->localeSwitcher->runWithLocale($locale, $callback);
85+
86+
return;
7487
}
88+
89+
$callback();
7590
}
7691
}

src/Symfony/Bridge/Twig/Mime/TemplatedEmail.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class TemplatedEmail extends Email
2020
{
2121
private ?string $htmlTemplate = null;
2222
private ?string $textTemplate = null;
23+
private ?string $locale = null;
2324
private array $context = [];
2425

2526
/**
@@ -42,6 +43,16 @@ public function htmlTemplate(?string $template): static
4243
return $this;
4344
}
4445

46+
/**
47+
* @return $this
48+
*/
49+
public function locale(?string $locale): static
50+
{
51+
$this->locale = $locale;
52+
53+
return $this;
54+
}
55+
4556
public function getTextTemplate(): ?string
4657
{
4758
return $this->textTemplate;
@@ -52,6 +63,11 @@ public function getHtmlTemplate(): ?string
5263
return $this->htmlTemplate;
5364
}
5465

66+
public function getLocale(): ?string
67+
{
68+
return $this->locale;
69+
}
70+
5571
/**
5672
* @return $this
5773
*/

src/Symfony/Bridge/Twig/Tests/Mime/BodyRendererTest.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
use Symfony\Component\Mime\HtmlToTextConverter\DefaultHtmlToTextConverter;
1919
use Symfony\Component\Mime\HtmlToTextConverter\HtmlToTextConverterInterface;
2020
use Symfony\Component\Mime\Part\Multipart\AlternativePart;
21+
use Symfony\Component\Translation\LocaleSwitcher;
2122
use Twig\Environment;
2223
use Twig\Loader\ArrayLoader;
24+
use Twig\TwigFunction;
2325

2426
class BodyRendererTest extends TestCase
2527
{
@@ -131,20 +133,36 @@ public function testRenderedOnceUnserializableContext()
131133
$this->assertEquals('Text', $email->getTextBody());
132134
}
133135

134-
private function prepareEmail(?string $text, ?string $html, array $context = [], HtmlToTextConverterInterface $converter = null): TemplatedEmail
136+
public function testRenderWithLocale()
137+
{
138+
$localeSwitcher = new LocaleSwitcher('en', []);
139+
$email = $this->prepareEmail(null, 'Locale: {{ locale_switcher_locale() }}', [], new DefaultHtmlToTextConverter(), $localeSwitcher, 'fr');
140+
141+
$this->assertEquals('Locale: fr', $email->getTextBody());
142+
$this->assertEquals('Locale: fr', $email->getHtmlBody());
143+
}
144+
145+
private function prepareEmail(?string $text, ?string $html, array $context = [], HtmlToTextConverterInterface $converter = null, LocaleSwitcher $localeSwitcher = null, string $locale = null): TemplatedEmail
135146
{
136147
$twig = new Environment(new ArrayLoader([
137148
'text' => $text,
138149
'html' => $html,
139150
'document.txt' => 'Some text document...',
140151
'image.jpg' => 'Some image data',
141152
]));
142-
$renderer = new BodyRenderer($twig, [], $converter);
153+
154+
if ($localeSwitcher instanceof LocaleSwitcher) {
155+
$twig->addFunction(new TwigFunction('locale_switcher_locale', [$localeSwitcher, 'getLocale']));
156+
}
157+
158+
$renderer = new BodyRenderer($twig, [], $converter, $localeSwitcher);
143159
$email = (new TemplatedEmail())
144160
->to('fabien@symfony.com')
145161
->from('helene@symfony.com')
162+
->locale($locale)
146163
->context($context)
147164
;
165+
148166
if (null !== $text) {
149167
$email->textTemplate('text');
150168
}

src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public function testSymfonySerialize()
5858
$e->to('you@example.com');
5959
$e->textTemplate('email.txt.twig');
6060
$e->htmlTemplate('email.html.twig');
61+
$e->locale('en');
6162
$e->context(['foo' => 'bar']);
6263
$e->addPart(new DataPart('Some Text file', 'test.txt'));
6364
$expected = clone $e;
@@ -66,6 +67,7 @@ public function testSymfonySerialize()
6667
{
6768
"htmlTemplate": "email.html.twig",
6869
"textTemplate": "email.txt.twig",
70+
"locale": "en",
6971
"context": {
7072
"foo": "bar"
7173
},

src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Symfony\Component\Form\Form;
2323
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
2424
use Symfony\Component\Mailer\Mailer;
25+
use Symfony\Component\Translation\LocaleSwitcher;
2526
use Symfony\Component\Translation\Translator;
2627
use Symfony\Contracts\Service\ResetInterface;
2728
use Twig\Extension\ExtensionInterface;
@@ -85,6 +86,10 @@ public function load(array $configs, ContainerBuilder $container)
8586
if ($htmlToTextConverter = $config['mailer']['html_to_text_converter'] ?? null) {
8687
$container->getDefinition('twig.mime_body_renderer')->setArgument('$converter', new Reference($htmlToTextConverter));
8788
}
89+
90+
if (ContainerBuilder::willBeAvailable('symfony/translation', LocaleSwitcher::class, ['symfony/framework-bundle'])) {
91+
$container->getDefinition('twig.mime_body_renderer')->setArgument('$localeSwitcher', new Reference('translation.locale_switcher'));
92+
}
8893
}
8994

9095
if ($container::willBeAvailable('symfony/asset-mapper', AssetMapper::class, ['symfony/twig-bundle'])) {

src/Symfony/Bundle/TwigBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"composer-runtime-api": ">=2.1",
2121
"symfony/config": "^6.1|^7.0",
2222
"symfony/dependency-injection": "^6.1|^7.0",
23-
"symfony/twig-bridge": "^6.3|^7.0",
23+
"symfony/twig-bridge": "^6.4|^7.0",
2424
"symfony/http-foundation": "^5.4|^6.0|^7.0",
2525
"symfony/http-kernel": "^6.2|^7.0",
2626
"twig/twig": "^2.13|^3.0.4"

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy