diff --git a/README.md b/README.md index cd9211bc8c2..cbbb7f2f7fb 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ addon | version | maintainers | summary [html_text](html_text/) | 17.0.1.0.0 | | Generate excerpts from any HTML field [iap_alternative_provider](iap_alternative_provider/) | 17.0.1.0.0 | sebastienbeau | Base module for providing alternative provider for iap apps [jsonifier](jsonifier/) | 17.0.1.0.0 | | JSON-ify data for all models +[mail_template_attachment_per_lang](mail_template_attachment_per_lang/) | 17.0.1.0.0 | | Set language specific attachments on mail templates. [module_analysis](module_analysis/) | 17.0.1.0.3 | legalsylvain | Add analysis tools regarding installed modules to know which installed modules comes from Odoo Core, OCA, or are custom modules [module_auto_update](module_auto_update/) | 17.0.1.0.0 | | Automatically update Odoo modules [module_change_auto_install](module_change_auto_install/) | 17.0.1.0.2 | legalsylvain | Customize auto installables modules by configuration diff --git a/mail_template_attachment_per_lang/README.rst b/mail_template_attachment_per_lang/README.rst new file mode 100644 index 00000000000..4e95530b566 --- /dev/null +++ b/mail_template_attachment_per_lang/README.rst @@ -0,0 +1,122 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +=========================================== +Mail Template Language Specific Attachments +=========================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:a075fae834285057e4a0f26c055240e2bc3b4586363b66887e80386a793fd60f + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/17.0/mail_template_attachment_per_lang + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-17-0/server-tools-17-0-mail_template_attachment_per_lang + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/server-tools&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module extends the functionality of mail templates. + +It allows you to configure attachments based on the language of the +partner or the language configured in the mail template (which is some +times different from the partner's language). + +- The email template's language could be + ``{{ object.partner_id.lang }}`` or ``{{ object.user_id.lang }}``, + where in the first case we want to send the email in the partner's + language and in the second case we want to send the email in the + user's language. + +For example you can use it to localize your company's terms of +agreements. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure a language dependent attachment: + +1. Activate the developer mode; +2. go to *Settings > Technical > Email > Templates*; +3. go to the form view of the template you want to change; +4. choose the *Language Attachment Method* you want to use; +5. change the field *Language Dependent Attachments* to what you want. + +Usage +===== + +When a template is selected in the mail composer, the attachments will +be automatically added based on the recipients language. The language of +the recipients can be configured on the Partner form view. When partners +with different languages are selected all attachments of the partners +languages will be added. + +To use the functionality: + +1. Configure a template (e.g. the sale order mail template) +2. go to a sale order; +3. click *Send by Email*; +4. the attachments are added based on the email's language or the + customer's language (which might not be the same), depending on the + configuration of the template. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Onestein + +Contributors +------------ + +- Dennis Sluijk + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mail_template_attachment_per_lang/__init__.py b/mail_template_attachment_per_lang/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/mail_template_attachment_per_lang/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/mail_template_attachment_per_lang/__manifest__.py b/mail_template_attachment_per_lang/__manifest__.py new file mode 100644 index 00000000000..c6b6afb5e23 --- /dev/null +++ b/mail_template_attachment_per_lang/__manifest__.py @@ -0,0 +1,12 @@ +{ + "name": "Mail Template Language Specific Attachments", + "summary": "Set language specific attachments on mail templates.", + "author": "Onestein,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/server-tools", + "category": "Localization", + "version": "17.0.1.0.0", + "license": "AGPL-3", + "depends": ["mail"], + "data": ["views/mail_template_view.xml", "security/ir.model.access.csv"], + "installable": True, +} diff --git a/mail_template_attachment_per_lang/i18n/it.po b/mail_template_attachment_per_lang/i18n/it.po new file mode 100644 index 00000000000..7c586f9b5b6 --- /dev/null +++ b/mail_template_attachment_per_lang/i18n/it.po @@ -0,0 +1,173 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mail_template_attachment_per_lang +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2026-02-17 10:09+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.15.2\n" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__assigned_attachment_ids +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__assigned_attachment_ids +msgid "Assigned Attachments" +msgstr "Allegati assegnati" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__attachment_id +msgid "Attachment" +msgstr "Allegato" + +#. module: mail_template_attachment_per_lang +#: model:ir.model,name:mail_template_attachment_per_lang.model_ir_attachment_language +msgid "Attachment Language" +msgstr "Lingua allegato" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__changeset_change_ids +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__changeset_change_ids +msgid "Changeset Changes" +msgstr "Modifiche dell'insieme di modifiche" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__changeset_ids +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__changeset_ids +msgid "Changesets" +msgstr "Insieme di modifiche" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__count_changesets +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__count_changesets +msgid "Count Changesets" +msgstr "Conteggio insieme di modifiche" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__count_pending_changeset_changes +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__count_pending_changeset_changes +msgid "Count Pending Changeset Changes" +msgstr "Conteggio modifiche dell'insieme di modifiche in attesa" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__count_pending_changesets +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__count_pending_changesets +msgid "Count Pending Changesets" +msgstr "Conteggio insieme di modifiche in attesa" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: mail_template_attachment_per_lang +#: model:ir.model,name:mail_template_attachment_per_lang.model_mail_template +msgid "Email Templates" +msgstr "Modelli e-mail" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__id +msgid "ID" +msgstr "ID" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__lang +msgid "Language" +msgstr "Lingua" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__ir_attachment_language_method +msgid "Language Attachment Method" +msgstr "Metodo allegato lingua" + +#. module: mail_template_attachment_per_lang +#: model_terms:ir.ui.view,arch_db:mail_template_attachment_per_lang.mail_template_form +msgid "Language Attachments" +msgstr "Allegati lingua" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__ir_attachment_language_ids +msgid "Language Dependent Attachments" +msgstr "Allegati dipendenti dalla lingua" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: mail_template_attachment_per_lang +#: model_terms:ir.ui.view,arch_db:mail_template_attachment_per_lang.mail_template_form +msgid "Method" +msgstr "Metodo" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields.selection,name:mail_template_attachment_per_lang.selection__mail_template__ir_attachment_language_method__partner_lang +msgid "Partner Language" +msgstr "Lingua del partner" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__smart_search +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__smart_search +msgid "Smart Search" +msgstr "Ricerca intelligente" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__mail_template_id +msgid "Template" +msgstr "Modello" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields.selection,name:mail_template_attachment_per_lang.selection__mail_template__ir_attachment_language_method__template_lang +msgid "Template Language" +msgstr "Lingua del modello" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,help:mail_template_attachment_per_lang.field_ir_attachment_language__count_pending_changeset_changes +#: model:ir.model.fields,help:mail_template_attachment_per_lang.field_mail_template__count_pending_changeset_changes +msgid "The number of pending changes of this record" +msgstr "Numero di modifiche di questo record in attesa" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,help:mail_template_attachment_per_lang.field_ir_attachment_language__count_pending_changesets +#: model:ir.model.fields,help:mail_template_attachment_per_lang.field_mail_template__count_pending_changesets +msgid "The number of pending changesets of this record" +msgstr "Numero di insiemi di modifiche in attesa di questo record" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,help:mail_template_attachment_per_lang.field_ir_attachment_language__count_changesets +#: model:ir.model.fields,help:mail_template_attachment_per_lang.field_mail_template__count_changesets +msgid "The overall number of changesets of this record" +msgstr "Numero totale di insiemi di modifiche di questo record" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__user_can_see_changeset +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__user_can_see_changeset +msgid "User Can See Changeset" +msgstr "L'utente può vedere l'insieme delle modifiche" diff --git a/mail_template_attachment_per_lang/i18n/mail_template_attachment_per_lang.pot b/mail_template_attachment_per_lang/i18n/mail_template_attachment_per_lang.pot new file mode 100644 index 00000000000..5f2c84a1ce2 --- /dev/null +++ b/mail_template_attachment_per_lang/i18n/mail_template_attachment_per_lang.pot @@ -0,0 +1,105 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mail_template_attachment_per_lang +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__attachment_id +msgid "Attachment" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model,name:mail_template_attachment_per_lang.model_ir_attachment_language +msgid "Attachment Language" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__create_uid +msgid "Created by" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__create_date +msgid "Created on" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__display_name +msgid "Display Name" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model,name:mail_template_attachment_per_lang.model_mail_template +msgid "Email Templates" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__id +msgid "ID" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__lang +msgid "Language" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__ir_attachment_language_method +msgid "Language Attachment Method" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model_terms:ir.ui.view,arch_db:mail_template_attachment_per_lang.mail_template_form +msgid "Language Attachments" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__ir_attachment_language_ids +msgid "Language Dependent Attachments" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__write_date +msgid "Last Updated on" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model_terms:ir.ui.view,arch_db:mail_template_attachment_per_lang.mail_template_form +msgid "Method" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields.selection,name:mail_template_attachment_per_lang.selection__mail_template__ir_attachment_language_method__partner_lang +msgid "Partner Language" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__smart_search +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_mail_template__smart_search +msgid "Smart Search" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields,field_description:mail_template_attachment_per_lang.field_ir_attachment_language__mail_template_id +msgid "Template" +msgstr "" + +#. module: mail_template_attachment_per_lang +#: model:ir.model.fields.selection,name:mail_template_attachment_per_lang.selection__mail_template__ir_attachment_language_method__template_lang +msgid "Template Language" +msgstr "" diff --git a/mail_template_attachment_per_lang/models/__init__.py b/mail_template_attachment_per_lang/models/__init__.py new file mode 100644 index 00000000000..3c0a006aade --- /dev/null +++ b/mail_template_attachment_per_lang/models/__init__.py @@ -0,0 +1,2 @@ +from . import ir_attachment_language +from . import mail_template diff --git a/mail_template_attachment_per_lang/models/ir_attachment_language.py b/mail_template_attachment_per_lang/models/ir_attachment_language.py new file mode 100644 index 00000000000..7d8f044a8ba --- /dev/null +++ b/mail_template_attachment_per_lang/models/ir_attachment_language.py @@ -0,0 +1,29 @@ +# Copyright 2018 Onestein +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class IrAttachmentLanguage(models.Model): + _name = "ir.attachment.language" + _description = "Attachment Language" + + mail_template_id = fields.Many2one( + comodel_name="mail.template", + string="Template", + required=True, + ondelete="cascade", + ) + + lang = fields.Selection( + selection=lambda self: self.env["res.lang"].get_installed(), + string="Language", + required=True, + ) + + attachment_id = fields.Many2one( + comodel_name="ir.attachment", + string="Attachment", + required=True, + ondelete="cascade", + ) diff --git a/mail_template_attachment_per_lang/models/mail_template.py b/mail_template_attachment_per_lang/models/mail_template.py new file mode 100644 index 00000000000..22f080a9c74 --- /dev/null +++ b/mail_template_attachment_per_lang/models/mail_template.py @@ -0,0 +1,64 @@ +# Copyright 2018 Onestein +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class MailTemplate(models.Model): + _inherit = "mail.template" + + ir_attachment_language_method = fields.Selection( + selection=[ + ("partner_lang", "Partner Language"), + ("template_lang", "Template Language"), + ], + string="Language Attachment Method", + default="partner_lang", + ) + ir_attachment_language_ids = fields.One2many( + string="Language Dependent Attachments", + comodel_name="ir.attachment.language", + inverse_name="mail_template_id", + ) + + def _generate_template_attachments( + self, res_ids, render_fields, render_results=None + ): + self.ensure_one() + res = super()._generate_template_attachments( + res_ids, render_fields, render_results=render_results + ) + recipient_values = {} # Get recipients (to work with partner_lang) + if self.ir_attachment_language_method == "partner_lang": + recipient_fields = {"email_cc", "email_to", "partner_to"} + self._generate_template_recipients( + res_ids, + recipient_fields, + render_results=recipient_values, + ) + lang_codes = dict(self._render_lang(res_ids)) + for res_id in res_ids: + values = res.setdefault(res_id, {}) + attached = [] + lang_code_list = [] + if self.env.context.get("template_preview_lang"): + lang = self.env.context.get("template_preview_lang") + lang_codes = {res_id: lang for res_id in res_ids} + lang_code_list = [lang_codes.get(res_id)] + elif self.ir_attachment_language_method == "partner_lang": + partner_ids = recipient_values.get(res_id, {}).get("partner_ids", []) + partners = self.env["res.partner"].browse(partner_ids) + lang_code_list = [p.lang for p in partners] + elif self.ir_attachment_language_method == "template_lang": + lang_code_list = [lang_codes.get(res_id)] + for lang_code in lang_code_list: + for lang_attach in self.ir_attachment_language_ids.filtered( + lambda a, lc=lang_code: a.lang == lc + ): + if lang_attach.id in attached: + continue + if "attachment_ids" not in values: + values["attachment_ids"] = [] + values["attachment_ids"].append(lang_attach.attachment_id.id) + attached.append(lang_attach.id) + return res diff --git a/mail_template_attachment_per_lang/pyproject.toml b/mail_template_attachment_per_lang/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/mail_template_attachment_per_lang/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/mail_template_attachment_per_lang/readme/CONFIGURE.md b/mail_template_attachment_per_lang/readme/CONFIGURE.md new file mode 100644 index 00000000000..40c4a04feff --- /dev/null +++ b/mail_template_attachment_per_lang/readme/CONFIGURE.md @@ -0,0 +1,7 @@ +To configure a language dependent attachment: + +1. Activate the developer mode; +2. go to *Settings \> Technical \> Email \> Templates*; +3. go to the form view of the template you want to change; +4. choose the *Language Attachment Method* you want to use; +5. change the field *Language Dependent Attachments* to what you want. diff --git a/mail_template_attachment_per_lang/readme/CONTRIBUTORS.md b/mail_template_attachment_per_lang/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..76a1463d268 --- /dev/null +++ b/mail_template_attachment_per_lang/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Dennis Sluijk \<\> diff --git a/mail_template_attachment_per_lang/readme/DESCRIPTION.md b/mail_template_attachment_per_lang/readme/DESCRIPTION.md new file mode 100644 index 00000000000..df11bf531b6 --- /dev/null +++ b/mail_template_attachment_per_lang/readme/DESCRIPTION.md @@ -0,0 +1,13 @@ +This module extends the functionality of mail templates. + +It allows you to configure attachments based on the language of the +partner or the language configured in the mail template (which is some +times different from the partner's language). + +- The email template's language could be `{{ object.partner_id.lang }}` + or `{{ object.user_id.lang }}`, where in the first case we want to + send the email in the partner's language and in the second case we + want to send the email in the user's language. + +For example you can use it to localize your company's terms of +agreements. diff --git a/mail_template_attachment_per_lang/readme/USAGE.md b/mail_template_attachment_per_lang/readme/USAGE.md new file mode 100644 index 00000000000..4fe8ad0c497 --- /dev/null +++ b/mail_template_attachment_per_lang/readme/USAGE.md @@ -0,0 +1,14 @@ +When a template is selected in the mail composer, the attachments will +be automatically added based on the recipients language. The language of +the recipients can be configured on the Partner form view. When partners +with different languages are selected all attachments of the partners +languages will be added. + +To use the functionality: + +1. Configure a template (e.g. the sale order mail template) +2. go to a sale order; +3. click *Send by Email*; +4. the attachments are added based on the email's language or the + customer's language (which might not be the same), depending on the + configuration of the template. diff --git a/mail_template_attachment_per_lang/security/ir.model.access.csv b/mail_template_attachment_per_lang/security/ir.model.access.csv new file mode 100644 index 00000000000..04a776e37d9 --- /dev/null +++ b/mail_template_attachment_per_lang/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_attachment_language_admin,ir.attachment.language admin,model_ir_attachment_language,base.group_no_one,1,1,1,1 +access_attachment_language_everyone,ir.attachment.language everyone,model_ir_attachment_language,,1,0,0,0 diff --git a/mail_template_attachment_per_lang/static/description/icon.png b/mail_template_attachment_per_lang/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/mail_template_attachment_per_lang/static/description/icon.png differ diff --git a/mail_template_attachment_per_lang/static/description/index.html b/mail_template_attachment_per_lang/static/description/index.html new file mode 100644 index 00000000000..8b3909817ef --- /dev/null +++ b/mail_template_attachment_per_lang/static/description/index.html @@ -0,0 +1,471 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Mail Template Language Specific Attachments

+ +

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

+

This module extends the functionality of mail templates.

+

It allows you to configure attachments based on the language of the +partner or the language configured in the mail template (which is some +times different from the partner’s language).

+
    +
  • The email template’s language could be +{{ object.partner_id.lang }} or {{ object.user_id.lang }}, +where in the first case we want to send the email in the partner’s +language and in the second case we want to send the email in the +user’s language.
  • +
+

For example you can use it to localize your company’s terms of +agreements.

+

Table of contents

+ +
+

Configuration

+

To configure a language dependent attachment:

+
    +
  1. Activate the developer mode;
  2. +
  3. go to Settings > Technical > Email > Templates;
  4. +
  5. go to the form view of the template you want to change;
  6. +
  7. choose the Language Attachment Method you want to use;
  8. +
  9. change the field Language Dependent Attachments to what you want.
  10. +
+
+
+

Usage

+

When a template is selected in the mail composer, the attachments will +be automatically added based on the recipients language. The language of +the recipients can be configured on the Partner form view. When partners +with different languages are selected all attachments of the partners +languages will be added.

+

To use the functionality:

+
    +
  1. Configure a template (e.g. the sale order mail template)
  2. +
  3. go to a sale order;
  4. +
  5. click Send by Email;
  6. +
  7. the attachments are added based on the email’s language or the +customer’s language (which might not be the same), depending on the +configuration of the template.
  8. +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Onestein
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/server-tools project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ + diff --git a/mail_template_attachment_per_lang/tests/__init__.py b/mail_template_attachment_per_lang/tests/__init__.py new file mode 100644 index 00000000000..67ff6ec1913 --- /dev/null +++ b/mail_template_attachment_per_lang/tests/__init__.py @@ -0,0 +1 @@ +from . import test_mail_template_attachment_per_lang diff --git a/mail_template_attachment_per_lang/tests/test_mail_template_attachment_per_lang.py b/mail_template_attachment_per_lang/tests/test_mail_template_attachment_per_lang.py new file mode 100644 index 00000000000..5debbb40f51 --- /dev/null +++ b/mail_template_attachment_per_lang/tests/test_mail_template_attachment_per_lang.py @@ -0,0 +1,221 @@ +# Copyright 2024 Onestein +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import base64 + +from odoo.tests import tagged + +from odoo.addons.mail.tests.common import MailCommon + + +@tagged("mail_template", "-at_install", "post_install") +class TestMailTemplateAttachmentPerLang(MailCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env["res.lang"]._activate_lang("fr_FR") + cls.partner_fr = cls.env["res.partner"].create( + { + "name": "French Partner", + "email": "french@example.com", + "lang": "fr_FR", + } + ) + cls.partner_en = cls.env["res.partner"].create( + { + "name": "English Partner", + "email": "english@example.com", + "lang": "en_US", + } + ) + + cls.attachment_fr = cls.env["ir.attachment"].create( + { + "name": "terms_fr.pdf", + "type": "binary", + "datas": base64.b64encode(b"French terms content"), + } + ) + cls.attachment_en = cls.env["ir.attachment"].create( + { + "name": "terms_en.pdf", + "type": "binary", + "datas": base64.b64encode(b"English terms content"), + } + ) + + cls.mail_template = cls.env["mail.template"].create( + { + "name": "Test i18n Template", + "model_id": cls.env.ref("base.model_res_partner").id, + "subject": "Test subject", + "body_html": "

Test body

", + "partner_to": "{{ object.id }}", + "lang": "{{ object.lang }}", + "ir_attachment_language_method": "template_lang", + "ir_attachment_language_ids": [ + ( + 0, + 0, + { + "lang": "fr_FR", + "attachment_id": cls.attachment_fr.id, + }, + ), + ( + 0, + 0, + { + "lang": "en_US", + "attachment_id": cls.attachment_en.id, + }, + ), + ], + } + ) + + def test_template_lang_method_french(self): + # Sending to a French partner should attach the French file + render_results = self.mail_template._generate_template( + [self.partner_fr.id], + [ + "attachment_ids", + "body_html", + "email_from", + "partner_to", + "report_template_ids", + "subject", + ], + ) + attachments = render_results[self.partner_fr.id].get("attachment_ids", []) + attachment_records = self.env["ir.attachment"].browse(attachments) + attachment_names = attachment_records.mapped("name") + self.assertIn("terms_fr.pdf", attachment_names) + self.assertNotIn("terms_en.pdf", attachment_names) + + def test_template_lang_method_english(self): + # Sending to an English partner should attach the English file + render_results = self.mail_template._generate_template( + [self.partner_en.id], + [ + "attachment_ids", + "body_html", + "email_from", + "partner_to", + "report_template_ids", + "subject", + ], + ) + attachments = render_results[self.partner_en.id].get("attachment_ids", []) + attachment_records = self.env["ir.attachment"].browse(attachments) + attachment_names = attachment_records.mapped("name") + self.assertIn("terms_en.pdf", attachment_names) + self.assertNotIn("terms_fr.pdf", attachment_names) + + def test_partner_lang_method(self): + # With partner_lang method, attachments match partner language + self.mail_template.ir_attachment_language_method = "partner_lang" + render_results = self.mail_template._generate_template( + [self.partner_fr.id], + [ + "attachment_ids", + "body_html", + "email_from", + "partner_to", + "report_template_ids", + "subject", + ], + ) + attachments = render_results[self.partner_fr.id].get("attachment_ids", []) + attachment_records = self.env["ir.attachment"].browse(attachments) + attachment_names = attachment_records.mapped("name") + self.assertIn("terms_fr.pdf", attachment_names) + self.assertNotIn("terms_en.pdf", attachment_names) + + def test_no_method_set(self): + # With no method set, no language-specific attachments are added + self.mail_template.ir_attachment_language_method = False + render_results = self.mail_template._generate_template( + [self.partner_fr.id], + [ + "attachment_ids", + "body_html", + "email_from", + "partner_to", + "report_template_ids", + "subject", + ], + ) + attachments = render_results[self.partner_fr.id].get("attachment_ids", []) + self.assertFalse(attachments) + + def test_batch_multiple_partners(self): + # Batch rendering attaches correct files per language + render_results = self.mail_template._generate_template( + [self.partner_fr.id, self.partner_en.id], + [ + "attachment_ids", + "body_html", + "email_from", + "partner_to", + "report_template_ids", + "subject", + ], + ) + fr_attachments = render_results[self.partner_fr.id].get("attachment_ids", []) + fr_attachment_records = self.env["ir.attachment"].browse(fr_attachments) + fr_names = fr_attachment_records.mapped("name") + en_attachments = render_results[self.partner_en.id].get("attachment_ids", []) + en_attachment_records = self.env["ir.attachment"].browse(en_attachments) + en_names = en_attachment_records.mapped("name") + self.assertIn("terms_fr.pdf", fr_names) + self.assertNotIn("terms_en.pdf", fr_names) + self.assertIn("terms_en.pdf", en_names) + self.assertNotIn("terms_fr.pdf", en_names) + + def test_send_mail_with_lang_attachments(self): + # Full send_mail flow includes language-specific attachments + with self.mock_mail_gateway(): + mail = self.mail_template.send_mail(self.partner_fr.id) + mail_record = self.env["mail.mail"].browse(mail) + attachment_names = mail_record.attachment_ids.mapped("name") + self.assertIn("terms_fr.pdf", attachment_names) + self.assertNotIn("terms_en.pdf", attachment_names) + + def test_partner_lang_with_fixed_template_lang(self): + # Test that even if the template body is forced to English, + # the attachments follow the recipient's language. + self.mail_template.write( + { + "lang": "en_US", + "partner_to": str(self.partner_en.id), + "ir_attachment_language_method": "partner_lang", + } + ) + # English recipient --> Should get English attachment + render_results = self.mail_template._generate_template( + [self.partner_en.id], + ["attachment_ids"], + ) + result = render_results[self.partner_en.id] + attachments = self.env["ir.attachment"].browse(result.get("attachment_ids", [])) + attachment_names = attachments.mapped("name") + self.assertIn("terms_en.pdf", attachment_names) + self.assertNotIn("terms_fr.pdf", attachment_names) + # Change recipient to French partner + # The body remains English (lang='en_US'), but attachments must switch to French + self.mail_template.write( + { + "partner_to": str(self.partner_fr.id), + } + ) + render_results = self.mail_template._generate_template( + [self.partner_fr.id], + ["attachment_ids"], + ) + result = render_results[self.partner_fr.id] + attachments = self.env["ir.attachment"].browse(result.get("attachment_ids", [])) + attachment_names = attachments.mapped("name") + # Verify that the logic correctly prioritized the recipient's language + self.assertIn("terms_fr.pdf", attachment_names) + self.assertNotIn("terms_en.pdf", attachment_names) diff --git a/mail_template_attachment_per_lang/views/mail_template_view.xml b/mail_template_attachment_per_lang/views/mail_template_view.xml new file mode 100644 index 00000000000..45a9207f2ce --- /dev/null +++ b/mail_template_attachment_per_lang/views/mail_template_view.xml @@ -0,0 +1,35 @@ + + + + + mail.template.form + mail.template + + + + + + + + + + + + + + + + diff --git a/setup/_metapackage/pyproject.toml b/setup/_metapackage/pyproject.toml index 4ea8ac45dbe..aab5f0b23c0 100644 --- a/setup/_metapackage/pyproject.toml +++ b/setup/_metapackage/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "odoo-addons-oca-server-tools" -version = "17.0.20260125.0" +version = "17.0.20260415.0" dependencies = [ "odoo-addon-attachment_logging>=17.0dev,<17.1dev", "odoo-addon-attachment_queue>=17.0dev,<17.1dev", @@ -30,6 +30,7 @@ dependencies = [ "odoo-addon-html_text>=17.0dev,<17.1dev", "odoo-addon-iap_alternative_provider>=17.0dev,<17.1dev", "odoo-addon-jsonifier>=17.0dev,<17.1dev", + "odoo-addon-mail_template_attachment_per_lang>=17.0dev,<17.1dev", "odoo-addon-module_analysis>=17.0dev,<17.1dev", "odoo-addon-module_auto_update>=17.0dev,<17.1dev", "odoo-addon-module_change_auto_install>=17.0dev,<17.1dev",