[REF] mail: split notification email generation by recipient language

RATIONALE

Naming conventions
  * content = core message / subject (+ other fields);
  * email layout = layouting applied to messages when sent to recipients who
    receive notifications by email e.g. access button, ...;
  * comment mode / mailing mode: composer main composition mode: posting on
    record(s) / sending a mailing on records;

Content situation when using a template to post on a composer

  * comment, monorecord mode: choose a template, content is rendered directly
    from template side according to 'lang' field definition -> ok;
  * comment, multirecord mode / mailing mode: choose a template, content is
    the raw content. At post / send, content is rendered and translated if
    matching template content -> ok;

Email layout situation when posting / mailing

  * comment: layout translated based on template 'lang' field definition
    or fallback on current user's lang;
  * mailing: no layout supported;

PURPOSE

Translate layout into recipient's lang when available, instead of either
current user or template defined lang. As it is contextual better translate
it to the end user lang.

SPECIFICATIONS

Move recipients and email layout rendering into a method returning an iterator.
That way a list of recipient groups (as given by '_notify_get_recipients') can
be split into sub-groups, with each having its own rendering values for
email notifications.

Do a split / recipient lang. It is already fetched when notifying messages
as part of '_get_recipient_data' returned values. We now return recipients
groups per lang and per usage type (user, portal, customer, ...). Rendering
values are computed for each group as several values depend on the lang (
actions, notification buttons, global layout, ...).

Layouts when posting are dependent on recipient lang, and not on current user
anymore. Template lang that forced the content lang is now used only as a
fallback when recipient have no lang.

SUMMARY

When a user in Spanish, posts using a template specifying the lang of the
customer on a record whose customer is in French, with a follower being
in English

  * content will be translated following template choice, aka french;
  * layouting for the french customer will be in french, layouting for the
    english customer is in english, while the core content is always the
    same and in french;

When a user in Spanish, posts some custome content on a record whose customer
is in French, with a follower being in English

  * content is whatever the user wrote;
  * layouting for the french customer will be in french, layouting for the
    english customer is in english, while the core content is always the
    same and in french;

Task-3046371 (Mail: Better Language Support in Composer)
Task-2555155 (Mail: Translate notification action/access buttons)
Task-3186426 (Mail: Support notification layout in template / email composer)

Part-of: odoo/odoo#106177
Co-authored-by: Julien Banken <jbn@odoo.com>
This commit is contained in:
Thibault Delavallée
2023-03-09 15:54:15 +01:00
co-authored by Julien Banken
parent 9887bd0c7b
commit b4d210b245
4 changed files with 310 additions and 110 deletions
+140 -40
View File
@@ -3012,36 +3012,9 @@ class MailThread(models.AbstractModel):
if not partners_data:
return True
lang = force_email_lang if force_email_lang else self.env.context.get('lang')
if not model_description:
model_description = self.with_context(lang=lang)._get_model_description(
msg_vals['model'] if msg_vals and msg_vals.get('model') else message.model
)
recipients_groups_list = self.with_context(lang=lang)._notify_get_recipients_classify(
base_mail_values = self._notify_by_email_get_base_mail_values(
message,
partners_data,
model_description,
msg_vals=msg_vals,
)
if not recipients_groups_list:
return True
force_send = self.env.context.get('mail_notify_force_send', force_send)
template_values = self.with_context(lang=lang)._notify_by_email_prepare_rendering_context(
message, msg_vals=msg_vals, model_description=model_description,
force_email_company=force_email_company,
force_email_lang=force_email_lang,
) # 10 queries
if subtitles:
template_values['subtitles'] = subtitles
email_layout_xmlid = msg_vals.get('email_layout_xmlid') if msg_vals else message.email_layout_xmlid
template_xmlid = email_layout_xmlid if email_layout_xmlid else 'mail.mail_notification_layout'
base_mail_values = self.with_context(lang=lang)._notify_by_email_get_base_mail_values(
message,
additional_values={'auto_delete': mail_auto_delete},
additional_values={'auto_delete': mail_auto_delete}
)
# Clean the context to get rid of residual default_* keys that could cause issues during
@@ -3057,18 +3030,23 @@ class MailThread(models.AbstractModel):
# loop on groups (customer, portal, user, ... + model specific like group_sale_salesman)
notif_create_values = []
recipients_max = 50
for recipients_group in recipients_groups_list:
for _lang, render_values, recipients_group in self._notify_get_classified_recipients_iterator(
message,
partners_data,
msg_vals=msg_vals,
model_description=model_description,
force_email_company=force_email_company,
force_email_lang=force_email_lang,
subtitles=subtitles,
):
# generate notification email content
mail_body = self._notify_by_email_render_layout(
message,
recipients_group,
msg_vals=msg_vals,
render_values=render_values,
)
recipients_ids = recipients_group.pop('recipients')
render_values = {**template_values, **recipients_group}
# {company, is_discussion, lang, message, model_description, record, record_name, signature, subtype, tracking_values, website_url}
# {actions, button_access, has_button_access, recipients}
mail_body = self.env['ir.qweb']._render(template_xmlid, render_values, minimal_qcontext=True, raise_if_not_found=False, lang=template_values['lang'])
if not mail_body:
_logger.warning('QWeb template %s not found or is empty when sending notification emails. Sending without layouting.', template_xmlid)
mail_body = message.body
mail_body = self.env['mail.render.mixin']._replace_local_links(mail_body)
# create email
for recipients_ids_chunk in split_every(recipients_max, recipients_ids):
@@ -3113,6 +3091,7 @@ class MailThread(models.AbstractModel):
# to prevent sending email during a simple update of the database
# using the command-line.
test_mode = getattr(threading.current_thread(), 'testing', False)
force_send = self.env.context.get('mail_notify_force_send', force_send)
if force_send and len(emails) < recipients_max and (not self.pool._init or test_mode):
# unless asked specifically, send emails after the transaction to
# avoid side effects due to emails being sent while the transaction fails
@@ -3132,6 +3111,86 @@ class MailThread(models.AbstractModel):
return True
def _notify_get_classified_recipients_iterator(
self, message, recipients_data, msg_vals=False,
model_description=False, force_email_company=False, force_email_lang=False, # rendering
subtitles=None):
""" Make groups of recipients, based on 'recipients_data' which is a list
of recipients informations. Purpose of this method is to group them by
main usage ('user', 'portal_user', 'follower', 'customer', ... see
@_notify_get_recipients_classify) and lang. Each group is linked to
an evaluation context to render the notification layout.
:param message: ``mail.message`` record to notify;
:param list recipients_data: see ``MailThread._notify_get_recipients``;
:param msg_vals: dictionary of values used to create the message. If
given it may be used to access values related to ``message``;
:param str model_description: description of current model, given to
avoid fetching it and easing translation support;
:param record force_email_company: <res.company> record used when rendering
notification layout. Otherwise computed based on current record;
:param str force_email_lang: when no specific lang is found this is the
default lang to use notably to compute model name or translate access
buttons;
:param list subtitles: optional list set as template value "subtitles";
:return: iterator based on recipients classified by lang, with their
rendering evaluation context. Each item is a tuple containing (
lang: used for rendering (customer language, forced email, default
environment language,
render_values: used to render the notification layout and translated
using lang,
recipients_group: a recipients group is a dict containing data
defined in "_notify_get_recipients_groups" like {
'active': if not, it is skipped in notification process (ease
inheritance to be already present);
'actions': list of actions to display as links or buttons in form
{'url': link of the action, 'title': link or button
string};
'button_access': main access document button information, {'url'
link of the access, 'title': link or button
string};
'has_button_access': display access document main button in email;
'notification_group_name': name of the group, to ease usage;
'recipients': list of partner IDs, will be fillup when evaluating
groups;
}
);
"""
lang_to_recipients = {}
for data in recipients_data:
lang_to_recipients.setdefault(
data.get('lang') or force_email_lang or self.env.lang,
[],
).append(data)
for lang, lang_recipients_data in lang_to_recipients.items():
record_wlang = self.with_context(lang=lang)
lang_model_description = model_description
if not lang_model_description:
lang_model_description = record_wlang._get_model_description(
msg_vals['model'] if msg_vals and msg_vals.get('model') else message.model
)
recipients_groups_list = record_wlang._notify_get_recipients_classify(
message,
lang_recipients_data,
lang_model_description,
msg_vals=msg_vals,
)
render_values = record_wlang._notify_by_email_prepare_rendering_context(
message,
msg_vals=msg_vals,
model_description=lang_model_description,
force_email_company=force_email_company,
force_email_lang=lang,
) # 10 queries
if subtitles:
render_values['subtitles'] = subtitles
for recipients_group in recipients_groups_list:
yield (lang, render_values, recipients_group)
def _notify_by_email_prepare_rendering_context(self, message, msg_vals=False,
model_description=False,
force_email_company=False,
@@ -3168,7 +3227,7 @@ class MailThread(models.AbstractModel):
"""
if msg_vals is False:
msg_vals = {}
lang = force_email_lang if force_email_lang else self.env.context.get('lang')
lang = force_email_lang if force_email_lang else self.env.lang
record_wlang = self.with_context(lang=lang)
# compute send user and its related signature; try to use self.env.user instead of browsing
@@ -3235,6 +3294,47 @@ class MailThread(models.AbstractModel):
'is_html_empty': is_html_empty,
}
def _notify_by_email_render_layout(self, message, recipients_group,
msg_vals=False,
render_values=None):
""" Renders the email layout for a given recipients group which
encapsulate the message body.
:param record message: <mail.message> record being notified. May be
void as 'msg_vals' superseeds it;
:param dict recipients_group: a dict containing data for the recipients,
see @ _notify_get_recipients_groups;
:param dict msg_vals: values dict used to create the message, allows to
skip message usage and spare some queries;
:param dict render_values: values to render the notification layout;
At this point expected values are
render_values: company, is_discussion, lang, message, model_description,
record, record_name, signature, subtype, tracking_values,
website_url
recipients_group: actions, button_access, has_button_access, recipients
:return str: rendered complete layout;
"""
if render_values is None:
render_values = {}
email_layout_xmlid = msg_vals.get('email_layout_xmlid') if msg_vals else message.email_layout_xmlid
template_xmlid = email_layout_xmlid if email_layout_xmlid else 'mail.mail_notification_layout'
render_values = {**render_values, **recipients_group}
mail_body = self.env['ir.qweb']._render(
template_xmlid,
render_values,
minimal_qcontext=True,
raise_if_not_found=False,
lang=render_values.get('lang', self.env.lang),
)
if not mail_body:
_logger.warning('QWeb template %s not found or is empty when sending notification emails. Sending without layouting.', template_xmlid)
mail_body = message.body
return mail_body
def _notify_by_email_get_base_mail_values(self, message, additional_values=None):
""" Return model-specific and message-related values to be used when
creating notification emails. It serves as a common basis for all
+5 -1
View File
@@ -221,7 +221,7 @@ class BaseModel(models.AbstractModel):
return E.activity(templates, string=self._description)
# ------------------------------------------------------------
# GATEWAY: NOTIFICATION
# DISCUSS
# ------------------------------------------------------------
def _mail_get_message_subtypes(self):
@@ -229,6 +229,10 @@ class BaseModel(models.AbstractModel):
'&', ('hidden', '=', False),
'|', ('res_model', '=', self._name), ('res_model', '=', False)])
# ------------------------------------------------------------
# GATEWAY: NOTIFICATION
# ------------------------------------------------------------
def _notify_by_email_get_headers(self):
""" Generate the email headers based on record """
if not self:
+96 -30
View File
@@ -1366,6 +1366,14 @@ class TestComposerResultsComment(TestMailComposer, CronMixinCase):
Test with and without notification layout specified.
Test with and without languages.
Setup with batch and langs
* record1: customer lang=es_ES
follower partner_employee_2 lang=en_US
3 new partners (en_US) created by template
* record2: customer lang=en_US
follower partner_employee_2 lang=en_US
3 new partners (en_US) created by template
"""
attachment_data = self._generate_attachments_data(2, self.template._name, self.template.id)
email_to_1 = 'test.to.1@test.example.com'
@@ -1465,10 +1473,32 @@ class TestComposerResultsComment(TestMailComposer, CronMixinCase):
self.assertFalse(self._mails)
# monorecord: force_send notifications
elif not batch:
# as there are recipients with different langs: we have
# 3 outgoing mails: partner_employee2 (user) then customers
# in two langs
if use_lang:
self.assertEqual(
len(self._new_mails), 3,
'Should have created 1 mail for user, then 2 for customers that belong to 2 langs')
# without lang, recipients are grouped by main usage aka user and customer
else:
self.assertEqual(
len(self._new_mails), 2,
'Should have created 1 mail for user, then 1 for customers')
self.assertEqual(self._new_mails.mapped('state'), ['sent'] * len(self._new_mails))
self.assertEqual(len(self._mails), 5, 'Should have sent 5 emails, one per recipient per record')
# multirecord: use email queue
else:
# see not-batch comment, then add 2 mails for the second
# record as all customers have same language
if use_lang:
self.assertEqual(
len(self._new_mails), 5,
'Should have created 3 mails for first record, then 2 for second')
else:
self.assertEqual(
len(self._new_mails), 4,
'Should have created 2 mails / record (one for user, one for customers)')
self.assertEqual(self._new_mails.mapped('state'), ['outgoing'] * len(self._new_mails))
self.assertEqual(len(self._mails), 0, 'Should have put emails in queue and not sent any emails')
# simulate cron sending emails
@@ -1505,18 +1535,36 @@ class TestComposerResultsComment(TestMailComposer, CronMixinCase):
freeze_time(self.reference_now + timedelta(days=3)):
self.env['mail.message.schedule'].sudo()._send_notifications_cron()
# global outgoing: one mail.mail (all customer recipients, then all employee recipients)
# and 5 emails, and 1 inbox notification (admin)
self.assertEqual(len(self._new_mails), 2 * len(test_records),
'Should have created 1 mail.mail per group per record')
# monorecord: force_send notifications
if not batch:
# as there are recipients with different langs: we have
# 3 outgoing mails: partner_employee2 (user) then customers
# in two langs
if use_lang:
self.assertEqual(
len(self._new_mails), 3,
'Should have created 1 mail for user, then 2 for customers that belong to 2 langs')
# without lang, recipients are grouped by main usage aka user and customer
else:
self.assertEqual(
len(self._new_mails), 2,
'Should have created 1 mail for user, then 1 for customers')
self.assertEqual(self._new_mails.mapped('state'), ['sent'] * len(self._new_mails))
self.assertEqual(len(self._mails), 5,
'Should have sent 5 emails, one per recipient per record')
self.assertEqual(len(self._mails), 5, 'Should have sent 5 emails, one per recipient per record')
# multirecord: use email queue
else:
# see not-batch comment, then add 2 mails for the second
# record as all customers have same language
if use_lang:
self.assertEqual(
len(self._new_mails), 5,
'Should have created 3 mails for first record, then 2 for second')
else:
self.assertEqual(
len(self._new_mails), 4,
'Should have created 2 mails / record (one for user, one for customers)')
self.assertEqual(self._new_mails.mapped('state'), ['outgoing'] * len(self._new_mails))
self.assertEqual(len(self._mails), 0,
'Should have kept force_send False parameter, and not sent any email')
self.assertEqual(len(self._mails), 0, 'Should have put emails in queue and not sent any emails')
# simulate cron sending emails
self.env['mail.mail'].sudo().process_email_queue()
@@ -1525,12 +1573,13 @@ class TestComposerResultsComment(TestMailComposer, CronMixinCase):
message = test_record.message_ids[0]
# check created mail.mail and outgoing emails. In comment
# 2 mails are generated (due to group-based layouting):
# 2 or 3 mails are generated (due to group-based layouting):
# - one for recipient that is a user
# - one for recipients that are customers
# Then each recipient receives its own outging email. See
# - one / two for recipients that are customers, one / lang
# Then each recipient receives its own outgoing email. See
# 'assertMailMail' for more details.
# user email (one user, one email)
if exp_lang == 'es_ES':
exp_body = f'SpanishBody for {test_record.name}'
exp_subject = f'SpanishSubject for {test_record.name}'
@@ -1555,29 +1604,46 @@ class TestComposerResultsComment(TestMailComposer, CronMixinCase):
'mail_server_id': self.mail_server_domain,
},
)
self.assertMailMail(test_record.customer_id + new_partners, 'sent',
mail_message=message,
author=author, # author is different in batch and monorecord mode (raw or rendered email_from)
email_values={
'body_content': exp_body,
'email_from': test_record.user_id.email_formatted, # set by template
'subject': exp_subject,
'attachments_info': [
{'name': 'AttFileName_00.txt', 'raw': b'AttContent_00', 'type': 'text/plain'},
{'name': 'AttFileName_01.txt', 'raw': b'AttContent_01', 'type': 'text/plain'},
{'name': f'TestReport for {test_record.name}.html', 'type': 'text/plain'},
{'name': f'TestReport2 for {test_record.name}.html', 'type': 'text/plain'},
]
},
fields_values={
'mail_server_id': self.mail_server_domain,
},
)
# Low-level checks on outgoing email for the recipient to
# customers emails (several customers, one or two emails depending
# on multi-lang testing environment)
if use_lang and test_record == test_records[0]:
# in this case, we are in a multi-lang customers testing
emails_recipients = [
test_record.customer_id, # es_ES
new_partners # en_US (default lang of new customers)
]
else:
# all recipients have same language, one email
emails_recipients = [test_record.customer_id + new_partners]
for recipients in emails_recipients:
self.assertMailMail(recipients, 'sent',
mail_message=message,
author=author, # author is different in batch and monorecord mode (raw or rendered email_from)
email_values={
'body_content': exp_body,
'email_from': test_record.user_id.email_formatted, # set by template
'subject': exp_subject,
'attachments_info': [
{'name': 'AttFileName_00.txt', 'raw': b'AttContent_00', 'type': 'text/plain'},
{'name': 'AttFileName_01.txt', 'raw': b'AttContent_01', 'type': 'text/plain'},
{'name': f'TestReport for {test_record.name}.html', 'type': 'text/plain'},
{'name': f'TestReport2 for {test_record.name}.html', 'type': 'text/plain'},
]
},
fields_values={
'mail_server_id': self.mail_server_domain,
},
)
# Specifically for the language-specific recipient, perform
# low-level checks on outgoing email for the recipient to
# check layouting and language. Note that standard layout
# is not tested against translations, only the custom one
# to ease translations checks.
# We could do the check for other layouts but it would be
# mainly noisy / duplicated check
email = self._find_sent_email(test_record.user_id.email_formatted, [test_record.customer_id.email_formatted])
self.assertTrue(bool(email), 'Email not found, check recipients')
+69 -39
View File
@@ -1518,8 +1518,9 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_composer_lang_template_comment(self):
""" When posting in comment mode, content is rendered using the lang
field of template. Notification layout lang is partly coming from
template, partly from environment (to be improved). """
field of template. Notification layout lang is the one from the
customer to personalize the context. When not found it fallbacks
on rendered template lang or environment lang. """
test_record = self.test_records[0].with_user(self.env.user)
test_template = self.test_template.with_user(self.env.user)
@@ -1566,9 +1567,8 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
else:
self.assertEqual(f'SpanishSubject for {test_record.name}', customer_email['subject'],
'Subject based on template should be translated')
# check notification layout content: currently partly translated
# based only on template definition
if exp_content_lang == 'en_US':
# check notification layout content: depends on customer lang
if exp_notif_lang == 'en_US':
self.assertNotIn('Spanish Layout para', body, 'Layout translation failed')
self.assertIn('English Layout for Lang Chatter Model', body,
'Layout / model translation failed')
@@ -1583,14 +1583,19 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
self.assertIn('NotificationButtonTitle', body,
'Groups-based action names translation failed')
else:
self.assertNotIn('English Layout for', body, 'Layout translation failed')
self.assertIn('Spanish Layout para Spanish Model Description', body,
'Layout / model translation failed')
self.assertNotIn('Lang Chatter Model', body, 'Model translation failed')
# check notification layout strings
self.assertIn('SpanishView Spanish Model Description', body,
'"View document" should be translated')
'"View document" translation failed')
self.assertNotIn(f'View {test_record._description}', body,
'"View document" should be translated')
'"View document" translation failed')
self.assertIn('SpanishButtonTitle', body,
'Groups-based action names should be translated')
'Groups-based action names translation failed')
self.assertNotIn('NotificationButtonTitle', body,
'Groups-based action names should be translated')
'Groups-based action names translation failed')
@users('employee')
@mute_logger('odoo.addons.mail.models.mail_mail')
@@ -1658,7 +1663,8 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_layout_email_lang_template(self):
""" Test language support when posting in batch using a template.
Content and layout are is translated based on template definition. """
Content is translated based on template definition, layout based on
customer lang. """
test_records = self.test_records.with_user(self.env.user)
test_template = self.test_template.with_user(self.env.user)
@@ -1673,7 +1679,11 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
record0_customer = self.env['res.partner'].search([('email_normalized', '=', 'test.record.1@test.customer.com')], limit=1)
self.assertTrue(record0_customer, 'Template usage should have created a contact based on record email')
for record, customer in zip(test_records, record0_customer + self.partner_2):
for record, customer, exp_notif_lang in zip(
test_records,
record0_customer + self.partner_2,
('en_US', 'es_ES') # new customer is en_US, partner_2 is es_ES
):
customer_email = self._find_sent_mail_wemail(customer.email_formatted)
self.assertTrue(customer_email)
@@ -1688,19 +1698,34 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
self.assertEqual(f'SpanishSubject for {record.name}', customer_email['subject'],
'Subject based on template should be translated')
# check notification layout translation
self.assertIn('Spanish Layout para', body,
'Layout content should be translated')
self.assertNotIn('English Layout for', body)
self.assertIn('Spanish Layout para Spanish Model Description', body,
'Model name should be translated')
self.assertIn('SpanishView Spanish Model Description', body,
'"View document" should be translated')
self.assertNotIn(f'View {test_records[1]._description}', body,
'"View document" should be translated')
self.assertIn('SpanishButtonTitle', body,
'Groups-based action names should be translated')
self.assertNotIn('NotificationButtonTitle', body,
'Fixme: groups-based action names should be translated')
if exp_notif_lang == 'en_US':
self.assertNotIn('Spanish Layout para', body,
'Layout content should be translated')
self.assertIn('English Layout for', body)
self.assertNotIn('Spanish Layout para Spanish Model Description', body,
'Model name should be translated')
self.assertNotIn('SpanishView Spanish Model Description', body,
'"View document" should be translated')
self.assertIn(f'View {test_records[1]._description}', body,
'"View document" should be translated')
self.assertNotIn('SpanishButtonTitle', body,
'Groups-based action names should be translated')
self.assertIn('NotificationButtonTitle', body,
'Groups-based action names should be translated')
else:
self.assertIn('Spanish Layout para', body,
'Layout content should be translated')
self.assertNotIn('English Layout for', body)
self.assertIn('Spanish Layout para Spanish Model Description', body,
'Model name should be translated')
self.assertIn('SpanishView Spanish Model Description', body,
'"View document" should be translated')
self.assertNotIn(f'View {test_records[1]._description}', body,
'"View document" should be translated')
self.assertIn('SpanishButtonTitle', body,
'Groups-based action names should be translated')
self.assertNotIn('NotificationButtonTitle', body,
'Groups-based action names should be translated')
@users('employee')
@mute_logger('odoo.addons.mail.models.mail_mail')
@@ -1743,29 +1768,34 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
)
# check created mail.mail and outgoing emails. One email
# is generated for 'partner_1' and 'partner_2' (same email
# as same configuration (aka all customers)).
_mail = self.assertMailMail(
self.partner_1 + self.partner_2, 'sent',
mail_message=message,
author=self.partner_employee,
email_values={
'body_content': '<p>Hi there</p>',
'email_from': self.partner_employee.email_formatted,
'subject': 'TeDeum',
},
)
# is generated for each partner 'partner_1' and 'partner_2'
# different language thus different layout
for partner in self.partner_1 + self.partner_2:
_mail = self.assertMailMail(
partner, 'sent',
mail_message=message,
author=self.partner_employee,
email_values={
'body_content': '<p>Hi there</p>',
'email_from': self.partner_employee.email_formatted,
'subject': 'TeDeum',
},
)
# Low-level checks on outgoing email for the recipient to
# check layouting and language. Note that standard layout
# is not tested against translations, only the custom one
# to ease translations checks.
for partner in self.partner_1 + self.partner_2:
for partner, exp_lang in zip(
self.partner_1 + self.partner_2,
('en_US', 'es_ES')
):
email = self._find_sent_email(
self.partner_employee.email_formatted,
[partner.email_formatted]
)
self.assertTrue(bool(email), 'Email not found, check recipients')
self.assertEqual(partner.lang, exp_lang, 'Test misconfiguration')
exp_layout_content_en = 'English Layout for Lang Chatter Model'
exp_layout_content_es = 'Spanish Layout para Spanish Model Description'
@@ -1774,7 +1804,7 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
exp_action_en = 'NotificationButtonTitle'
exp_action_es = 'SpanishButtonTitle'
if email_layout_xmlid:
if employee_lang == 'es_ES':
if exp_lang == 'es_ES':
self.assertIn(exp_layout_content_es, email['body'])
self.assertIn(exp_button_es, email['body'])
self.assertIn(exp_action_es, email['body'])
@@ -1784,7 +1814,7 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
self.assertIn(exp_action_en, email['body'])
else:
# check default layouting applies
if employee_lang == 'es_ES':
if exp_lang == 'es_ES':
self.assertIn('html lang="es_ES"', email['body'])
else:
self.assertIn('html lang="en_US"', email['body'])