Мне любопытно, как эффективно создавать электронные письма в многоязычном приложении.
Для согласования всех ответов: допустим, у вас есть типичный коммерческий информационный бюллетень с большим количеством изображений, разметки и, конечно же, большим количеством текстовых абзацев. Предположим, что весь текст НЕ поступает из базы данных, но должен быть жестко закодирован. Более того, некоторые слова в этих абзацах могут быть выделены жирным шрифтом, подчеркнуты, ... Информационный бюллетень будет отправлен в предпочтительном для подписчика языке.
Как я могу создать систему, которая справится с этим?
trans() и определять все переводы в папке Laravel язык? Как насчет части разметки отдельных слов? Мне как-то кажется неправильным включение HTML-тегов в языковые файлы.





Я бы выбрал первый вариант с некоторыми изменениями, используя анализатор уценки в электронных письмах, поэтому вы не будете включать HTML внутри языковых файлов, вы будете отправлять проанализированные строки разметки в шаблон лезвия:
Каждый раз, когда требуется изменение шаблона, вам не нужно обновлять каждый шаблон для каждого языка.
Коды локализации уже реализованы в движке шаблонов Laravel & Blade.
Для ежедневного электронного письма кампании вы должны создать только один шаблон (может быть, еще один для таких языков, как RTL) и строки перевода п х м, где п обозначает каждую строку, содержащуюся в шаблоне, а
Вы сможете использовать строковые модификаторы, такие как сингулярность / множественность, замена и расширение системы своими собственными помощниками.
Например, простое электронное письмо в формате html может быть создано следующим образом (с использованием Laravel 5.6):
Структура файлов перевода
/resources
/lang
/en
/dailydigest.php
/de
/dailydigest.php
Отправляем по почте DailyDigest.php
<?php
namespace App\Mail;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Markdown;
use Illuminate\Queue\SerializesModels;
class DailyDigest extends Mailable
{
use Queueable;
protected $user;
public function __construct($user)
{
$this->user= $user;
}
public function build()
{
return $this
->from("[email protected]")
->view('emails.dailydigest', [
'user' => $this->user,
'messageSection1' => Markdown::parse(Lang::get("dailydigest.message1",[],$this->user->locale)),
'messageImage1' => 'http://example.com/images/test.png',
'messageSection2' => Markdown::parse(Lang::get("dailydigest.message2",[],$this->user->locale)),
// if it's a language specific image
'messageImage2' => Lang::get("dailydigest.image2",[],$this->user->locale),
]);
}
}
Шаблон /resources/views/emails/dailydigest.blade.php
Стандартный шаблон лезвия, содержащий HTML и директивы лезвия, созданный для ежедневного дайджеста электронной почты.
Контроллер SendDailyDigest.php
<?php
namespace App\Http\Controllers;
use App\User;
use App\Mail\DailyDigest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Http\Controllers\Controller;
class DailyDigestController extends Controller
{
/**
* Send the dailydigest to all members.
*
* @param Request $request
* @return Response
*/
public function send(Request $request)
{
$users = App\User::all();
// build the email message with the users locale and add to queue
foreach($users as $user){
Mail::to($user->email)
->send(new DailyDigest($user))
->queue("digest");
}
}
}
И есть публикация, которую я недавно нашел:
https://laravel-news.com/laravel-campaign-monitor
Обновил свой ответ.
Ваш ответ предполагает, что ежедневный дайджест почты всегда имеет одинаковую структуру. Как насчет того, чтобы структура / макет могли меняться между двумя выпусками?
Затем вы можете создать другой объект Mailable с этим шаблоном и отправить его. Есть способ, которым вы можете автоматизировать это, сохранить шаблон в файле, отличном от UI, как это делают mailchimp и другие службы, и получить это имя шаблона из базы данных,
Для информационных бюллетеней со статическим содержанием:
Система локализации Laravel хорошо работает для строк в приложении, но для текстового контента в электронном письме эти определения будут громоздкими в обслуживании, особенно для контента, который содержит встроенную разметку или который регулярно изменяется. Шаблоны с большим количеством вызовов trans() также отображаются медленнее, особенно при пакетной обработке тысяч электронных писем.
Если контент пишет кто-то другой, гораздо проще добавить несколько директив Blade там, где это необходимо, чем извлекать каждый фрагмент текста в запись локализации. Помните, нам нужно повторить эту работу для информационного бюллетеня каждый.
Вместо этого просто напишите содержимое прямо в шаблон и используйте иерархию именования для сообщений, переведенных на разные языки. Извлеките структурные элементы и элементы отображения в компоненты многократного использования, чтобы минимизировать количество разметки, смешанной с содержимым.
Наша иерархия файлов шаблонов может выглядеть так:
resources/views/newsletters/
├── components/
│ └── article_summary.blade.php
├── en/
│ └── 2018-01-01.blade.php
├── es/
│ └── 2018-01-01.blade.php
├── fr/
│ └── 2018-01-01.blade.php
└── newsletter.blade.php
Главный шаблон newsletter.blade.php содержит основные элементы, отображаемые в каждом информационном бюллетене, такие как заголовок, логотип и нижний колонтитул. Он будет @include() в соответствующем теле информационного бюллетеня в зависимости от локали пользователя и даты публикации:
{{-- ... common header markup ... --}}
@include("newsletters.$locale.$date")
{{-- ... common footer markup ... --}}
Каждый шаблон в папках локализации содержит текст сообщения на этом языке с небольшим количеством встроенного HTML или уценки для форматирования по мере необходимости. Вот пример:
# Newsletter Title
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc
finibus sapien nec sapien dictum, vitae dictum dolor mattis.
Nunc bibendum id augue...
@component('newsletters.components.article_summary', [
'title' => 'Article Title 1',
'fullArticleUrl' => 'http://...',
])
Ut aliquet lobortis leo, cursus volutpat mi convallis ut.
Vivamus id orci ut quam rhoncus eleifend. Nulla condimentum...
@endcomponent
@component('newsletters.components.article_summary', [
'title' => 'Article Title 2',
'fullArticleUrl' => 'http://...',
])
Donec non finibus tellus, efficitur tincidunt leo. Nam nibh
augue, consectetur tincidunt dui et, fermentum dictum eros...
@endcomponent
Как мы видим, мало что отвлекает от содержания сообщения. Компонент article_summary скрывает разметку от тела сообщения:
<div class = "summary">
<a href = "{{ $fullArticleUrl }}">
<h2>{{ $title }}</h2>
</a>
<p>{{ $slot }}</p>
</div>
Используя компоненты, мы можем свободно изменять макет в каждом информационном бюллетене и избегать частого переписывания разметки. Laravel включает некоторые полезные встроенные компоненты для сообщений уценки.
Чтобы отправить сообщение, мы просто передаем языковой стандарт и дату информационного бюллетеня, которые наш главный шаблон будет разрешать из доступных языков:
public function build()
{
return $this->->markdown('newsletters.newsletter')->with([
'locale' => $this->user->locale,
'date' => '2018-01-01',
]);
}
В заключение, нам не нужно полностью отказываться от использования trans(). В некоторых случаях это может иметь смысл, например, в общих компонентах. Для большей части контента мы получаем удобочитаемость и удобство обслуживания, записывая его непосредственно в шаблоне.
Не могли бы вы уточнить, используя пример кода / структур? Кроме того, мне трудно увидеть сложный макет информационного бюллетеня, определенный в markdown.