8000 feature #51690 [Mime] Add `TemplatedEmail::locale()` to set the local… · symfony/symfony@decb566 · GitHub
[go: up one dir, main page]

Skip to content

Commit decb566

Browse files
committed
feature #51690 [Mime] Add TemplatedEmail::locale() to set the locale for the email rendering (alexander-schranz)
This PR was squashed before being merged into the 6.4 branch. Discussion ---------- [Mime] Add `TemplatedEmail::locale()` to set the locale for the email rendering | Q | A | ------------- | --- | Branch? | 6.4 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead --> | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> Add LocaleSwitcher to TemplatedEmail BodyRenderer. Currently it is not possible to render a twig template or a converter in a specific locale context. It is common to send the email in the language of the receiver. ### Usage ```php $email = (new TemplatedEmail()) ->to('fabien@symfony.com') ->from('helene@symfony.com') ->subject('Hallo!') ->locale('de') ->textTemplate('email.txt.twig') ->htmlTemplate('email.html.twig') ->context($context) ; ``` Commits ------- d912384 [Mime] Add `TemplatedEmail::locale()` to set the locale for the email rendering
2 parents 9778b08 + d912384 commit decb566

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
< 4644 td data-grid-cell-id="diff-6c34cc3e82c0d42d9046c34f9c3e9924f5c3da6c64082c3fbf7f2d512c3e523d-24-24-1" data-selected="false" role="gridcell" style="background-color:var(--bgColor-default);text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative diff-line-number-neutral left-side">24
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",
24
"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)
0