diff --git a/connector_wordpress_wpml/README.rst b/connector_wordpress_wpml/README.rst new file mode 100644 index 000000000..4c7f698a4 --- /dev/null +++ b/connector_wordpress_wpml/README.rst @@ -0,0 +1,73 @@ +======================== +Connector WordPress WMPL +======================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:d23d756741cd2b3f004e61155d338ccb1a5c43949541285f54121e019b39c117 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/licence-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-NuoBiT%2Fodoo--addons-lightgray.png?logo=github + :target: https://github.com/NuoBiT/odoo-addons/tree/18.0/connector_wordpress_wpml + :alt: NuoBiT/odoo-addons + +|badge1| |badge2| |badge3| + +- This module works with plugin WordPress Multi Language. +- https://wpml.org/ + +On WPML settings uncheck the options + +- When uploading media to the Media library, make it available in all + languages. +- Duplicate media attachments for translations. + +If we don't do this, the media files will be created once for each +language, which it can be a problem for the capacity of the server. + +**Table of contents** + +.. contents:: + :local: + +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 +------- + +* NuoBiT Solutions SL + +Contributors +------------ + +- `NuoBiT `__: + + - Kilian Niubo kniubo@nuobit.com + - Deniz Gallo dgallo@nuobit.com + +Maintainers +----------- + +This module is part of the `NuoBiT/odoo-addons `_ project on GitHub. + +You are welcome to contribute. diff --git a/connector_wordpress_wpml/__init__.py b/connector_wordpress_wpml/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/connector_wordpress_wpml/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/connector_wordpress_wpml/__manifest__.py b/connector_wordpress_wpml/__manifest__.py new file mode 100644 index 000000000..b670a211c --- /dev/null +++ b/connector_wordpress_wpml/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# Copyright 2026 NuoBiT Solutions SL - Deniz Gallo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +{ + "name": "Connector WordPress WMPL", + "version": "18.0.1.0.0", + "author": "NuoBiT Solutions SL", + "license": "AGPL-3", + "category": "Connector", + "website": "https://github.com/NuoBiT/odoo-addons", + "depends": [ + "connector_wordpress", + ], + "data": [ + "views/ir_attachment_views.xml", + "views/res_lang_views.xml", + "views/wordpress_backend_view.xml", + ], +} diff --git a/connector_wordpress_wpml/models/__init__.py b/connector_wordpress_wpml/models/__init__.py new file mode 100644 index 000000000..07f060dd6 --- /dev/null +++ b/connector_wordpress_wpml/models/__init__.py @@ -0,0 +1,3 @@ +from . import backend +from . import ir_attachment +from . import res_lang diff --git a/connector_wordpress_wpml/models/backend/__init__.py b/connector_wordpress_wpml/models/backend/__init__.py new file mode 100644 index 000000000..baacd255d --- /dev/null +++ b/connector_wordpress_wpml/models/backend/__init__.py @@ -0,0 +1 @@ +from . import backend diff --git a/connector_wordpress_wpml/models/backend/backend.py b/connector_wordpress_wpml/models/backend/backend.py new file mode 100644 index 000000000..ab47b8739 --- /dev/null +++ b/connector_wordpress_wpml/models/backend/backend.py @@ -0,0 +1,26 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# Copyright 2026 NuoBiT Solutions SL - Deniz Gallo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import logging + +from odoo import _, api, models +from odoo.exceptions import ValidationError + +_logger = logging.getLogger(__name__) + + +class WordPressBackend(models.Model): + _inherit = "wordpress.backend" + + @api.constrains("lang_ids") + def check_lang_ids(self): + for rec in self: + for lang in rec.lang_ids: + if not lang.wordpress_wpml_lang_code: + raise ValidationError( + _( + "The language %(lang)s has no WPML code, please define " + "this code in language before using it." + ) + % {"lang": lang.name} + ) diff --git a/connector_wordpress_wpml/models/ir_attachment/__init__.py b/connector_wordpress_wpml/models/ir_attachment/__init__.py new file mode 100644 index 000000000..b6ea9e5ec --- /dev/null +++ b/connector_wordpress_wpml/models/ir_attachment/__init__.py @@ -0,0 +1,5 @@ +from . import adapter +from . import binder +from . import binding +from . import export_mapper +from . import exporter diff --git a/connector_wordpress_wpml/models/ir_attachment/adapter.py b/connector_wordpress_wpml/models/ir_attachment/adapter.py new file mode 100644 index 000000000..4c408d0c1 --- /dev/null +++ b/connector_wordpress_wpml/models/ir_attachment/adapter.py @@ -0,0 +1,27 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# Copyright 2026 NuoBiT Solutions SL - Deniz Gallo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +from odoo.addons.component.core import Component + + +class WordPressIrAttachment(Component): + _inherit = "wordpress.ir.attachment.adapter" + + # def _get_search_fields(self): + # res = super()._get_search_fields() + # res.append("lang") + # return res + + def create(self, data): # pylint: disable=W8106 + lang = data.pop("lang") + res = super().create(data) + res["lang"] = lang + return res + + def write(self, external_id, data): # pylint: disable=W8106 + lang = data.pop("lang") + external_id_values = self.binder_for().id2dict(external_id, in_field=False) + res = self._exec("put", f"media/{external_id_values['id']}", data=data) + res["lang"] = lang + return res diff --git a/connector_wordpress_wpml/models/ir_attachment/binder.py b/connector_wordpress_wpml/models/ir_attachment/binder.py new file mode 100644 index 000000000..b68a8ad87 --- /dev/null +++ b/connector_wordpress_wpml/models/ir_attachment/binder.py @@ -0,0 +1,52 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +from odoo.addons.component.core import Component + + +class WordPressIrAttachmentBinder(Component): + _inherit = "wordpress.ir.attachment.binder" + + @property + def external_alt_id(self): + return super().external_alt_id + ["lang"] + + # TODO: This funtions are the same as product wpml mixin + def get_binding_domain(self, record): + domain = super().get_binding_domain(record) + wp_wpml_code = self.env["res.lang"]._get_wpml_code_from_iso_code( + record._context.get("lang") + ) + if wp_wpml_code: + domain += [ + ( + "wordpress_lang", + "=", + wp_wpml_code, + ) + ] + return domain + + def _additional_external_binding_fields(self, external_data, relation): + # TODO: this additional fields probably should be + # included in binding as m2o to res lang on upper binder + return { + **super()._additional_external_binding_fields(external_data, relation), + "wordpress_lang": external_data.get("lang") or self.env.context.get("lang"), + } + + def _get_external_record_alt(self, relation, id_values): + res = super()._get_external_record_alt(relation, id_values) + if res: + relation_wp_lang = self.env["res.lang"]._get_wpml_code_from_iso_code( + relation.env.context.get("lang") + ) + if res.get("lang") != relation_wp_lang: + if res.get("translations") and res["translations"].get( + relation_wp_lang + ): + adapter = self.component(usage="backend.adapter") + res = adapter.read(res["translations"][relation_wp_lang]) + else: + return None + return res diff --git a/connector_wordpress_wpml/models/ir_attachment/binding.py b/connector_wordpress_wpml/models/ir_attachment/binding.py new file mode 100644 index 000000000..0851b82ee --- /dev/null +++ b/connector_wordpress_wpml/models/ir_attachment/binding.py @@ -0,0 +1,34 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +from odoo import fields, models + + +class WordPressIrAttachment(models.Model): + _inherit = "wordpress.ir.attachment" + + wordpress_lang = fields.Char( + string="Language", + required=True, + ) + + # we overwrite the db constraints, so they must have exactly the same name + # as the parent inherited + _sql_constraints = [ + ( + "internal_uniq", + "unique(backend_id, odoo_id, wordpress_lang)", + "A binding already exists with the same Internal ID (odoo_id)", + ) + ] + + def _prepare_relation(self, relation, record): + res = super()._prepare_relation(relation, record) + context = relation.env.context.copy() + iso_lang = self.env["res.lang"]._get_iso_code_from_wpml_code( + record.wordpress_lang + ) + if iso_lang: + context.update({"lang": iso_lang, "resync_export": True}) + relation.env.context = context + return res diff --git a/connector_wordpress_wpml/models/ir_attachment/export_mapper.py b/connector_wordpress_wpml/models/ir_attachment/export_mapper.py new file mode 100644 index 000000000..576d9615b --- /dev/null +++ b/connector_wordpress_wpml/models/ir_attachment/export_mapper.py @@ -0,0 +1,18 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +from odoo.addons.component.core import Component +from odoo.addons.connector.components.mapper import changed_by, mapping + + +class WordPressIrAttachmentExportMapper(Component): + _inherit = "wordpress.ir.attachment.export.mapper" + + @changed_by("lang") + @mapping + def lang(self, record): + # TODO: unify this code. Probably do a function in res lang + lang = self.env["res.lang"]._get_wpml_code_from_iso_code( + record._context.get("lang") + ) + return {"lang": lang} diff --git a/connector_wordpress_wpml/models/ir_attachment/exporter.py b/connector_wordpress_wpml/models/ir_attachment/exporter.py new file mode 100644 index 000000000..a878600ad --- /dev/null +++ b/connector_wordpress_wpml/models/ir_attachment/exporter.py @@ -0,0 +1,25 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +from odoo.addons.component.core import Component + + +class WordPressIrAttachmentExporter(Component): + _inherit = "wordpress.ir.attachment.record.direct.exporter" + + def run(self, relation, always=True, internal_fields=None): + res = [] + # langs_to_export = [] + # if relation.env.context.get("resync_export"): + # langs_to_export.append(relation.env.context.get("lang")) + # else: + langs_to_export = self.backend_record.lang_ids.mapped("code") + + for lang in langs_to_export: + result = super().run( + relation.with_context(lang=lang), + always=always, + internal_fields=internal_fields, + ) + res.append(result) + return res diff --git a/connector_wordpress_wpml/models/res_lang.py b/connector_wordpress_wpml/models/res_lang.py new file mode 100644 index 000000000..81fba4caf --- /dev/null +++ b/connector_wordpress_wpml/models/res_lang.py @@ -0,0 +1,40 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import logging + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + +_logger = logging.getLogger(__name__) + + +class Lang(models.Model): + _inherit = "res.lang" + + wordpress_wpml_lang_code = fields.Char() + + _sql_constraints = [ + ( + "wordpress_wpml_lang_code_uniq", + "unique(wordpress_wpml_lang_code)", + "The WPML lang code must be unique !", + ), + ] + + @api.model + def _get_wpml_code_from_iso_code(self, code): + lang = self.env["res.lang"].search([("code", "=", code)]) + if not lang: + raise ValidationError(_("Language not found with code %s") % code) + if not lang.wordpress_wpml_lang_code: + raise ValidationError(_("WPML code not found for lang: %s") % lang) + return lang.wordpress_wpml_lang_code + + @api.model + def _get_iso_code_from_wpml_code(self, wpml_code): + lang = self.env["res.lang"].search( + [("wordpress_wpml_lang_code", "=", wpml_code)] + ) + if not lang: + raise ValidationError(_("Language not found with wpml code %s") % wpml_code) + return lang.iso_code diff --git a/connector_wordpress_wpml/pyproject.toml b/connector_wordpress_wpml/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/connector_wordpress_wpml/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/connector_wordpress_wpml/readme/CONTRIBUTORS.md b/connector_wordpress_wpml/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..5d535bfca --- /dev/null +++ b/connector_wordpress_wpml/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- [NuoBiT](https://www.nuobit.com): + - Kilian Niubo + - Deniz Gallo diff --git a/connector_wordpress_wpml/readme/DESCRIPTION.md b/connector_wordpress_wpml/readme/DESCRIPTION.md new file mode 100644 index 000000000..440455250 --- /dev/null +++ b/connector_wordpress_wpml/readme/DESCRIPTION.md @@ -0,0 +1,10 @@ +- This module works with plugin WordPress Multi Language. +- + +On WPML settings uncheck the options +- When uploading media to the Media library, make it available in all + languages. +- Duplicate media attachments for translations. + +If we don't do this, the media files will be created once for each +language, which it can be a problem for the capacity of the server. diff --git a/connector_wordpress_wpml/static/description/icon.png b/connector_wordpress_wpml/static/description/icon.png new file mode 100644 index 000000000..1cd641e79 Binary files /dev/null and b/connector_wordpress_wpml/static/description/icon.png differ diff --git a/connector_wordpress_wpml/static/description/index.html b/connector_wordpress_wpml/static/description/index.html new file mode 100644 index 000000000..1d4337107 --- /dev/null +++ b/connector_wordpress_wpml/static/description/index.html @@ -0,0 +1,431 @@ + + + + + +Connector WordPress WMPL + + + +
+

Connector WordPress WMPL

+ + +

Beta License: AGPL-3 NuoBiT/odoo-addons

+ +

On WPML settings uncheck the options

+
    +
  • When uploading media to the Media library, make it available in all +languages.
  • +
  • Duplicate media attachments for translations.
  • +
+

If we don’t do this, the media files will be created once for each +language, which it can be a problem for the capacity of the server.

+

Table of contents

+ +
+

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

+
    +
  • NuoBiT Solutions SL
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is part of the NuoBiT/odoo-addons project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/connector_wordpress_wpml/views/ir_attachment_views.xml b/connector_wordpress_wpml/views/ir_attachment_views.xml new file mode 100644 index 000000000..cb4393a0f --- /dev/null +++ b/connector_wordpress_wpml/views/ir_attachment_views.xml @@ -0,0 +1,32 @@ + + + + + wordpress.ir.attachment.view.form + wordpress.ir.attachment + + + + + + + + + wordpress.ir.attachment.view.list + wordpress.ir.attachment + + + + + + + + diff --git a/connector_wordpress_wpml/views/res_lang_views.xml b/connector_wordpress_wpml/views/res_lang_views.xml new file mode 100644 index 000000000..060821eb6 --- /dev/null +++ b/connector_wordpress_wpml/views/res_lang_views.xml @@ -0,0 +1,23 @@ + + + + res.lang.list + res.lang + + + + + + + + + res.lang.form + res.lang + + + + + + + + diff --git a/connector_wordpress_wpml/views/wordpress_backend_view.xml b/connector_wordpress_wpml/views/wordpress_backend_view.xml new file mode 100644 index 000000000..7bf97fe3d --- /dev/null +++ b/connector_wordpress_wpml/views/wordpress_backend_view.xml @@ -0,0 +1,22 @@ + + + + + wordpress.backend.form + wordpress.backend + + + + + + + + diff --git a/setup/connector_wordpress_wpml/odoo/addons/connector_wordpress_wpml b/setup/connector_wordpress_wpml/odoo/addons/connector_wordpress_wpml new file mode 120000 index 000000000..295c048a2 --- /dev/null +++ b/setup/connector_wordpress_wpml/odoo/addons/connector_wordpress_wpml @@ -0,0 +1 @@ +../../../../connector_wordpress_wpml \ No newline at end of file diff --git a/setup/connector_wordpress_wpml/setup.py b/setup/connector_wordpress_wpml/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/connector_wordpress_wpml/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 000000000..f6e0c2e2c --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,9 @@ +odoo-addon-website_sale_stock_variant@git+https://github.com/nuobit/odoo-addons.git@refs/pull/825/head#subdirectory=website_sale_stock_variant +odoo-addon-website_sale_extra_fields@git+https://github.com/nuobit/odoo-addons.git@refs/pull/826/head#subdirectory=website_sale_extra_fields +odoo-addon-connector_wordpress@git+https://github.com/nuobit/odoo-addons.git@refs/pull/876/head#subdirectory=connector_wordpress +odoo-addon-connector_extension_woocommerce@git+https://github.com/nuobit/odoo-addons.git@refs/pull/875/head#subdirectory=connector_extension_woocommerce +odoo-addon-tools_mimetypes_extension@git+https://github.com/nuobit/odoo-addons.git@refs/pull/878/head#subdirectory=tools_mimetypes_extension +odoo-addon-website_sale_variant@git+https://github.com/nuobit/odoo-addons.git@refs/pull/824/head#subdirectory=website_sale_variant +odoo-addon-website_sale_product_document@git+https://github.com/nuobit/odoo-addons.git@refs/pull/827/head#subdirectory=website_sale_product_document +odoo-addon-connector_extension_wordpress@git+https://github.com/nuobit/odoo-addons.git@refs/pull/877/head#subdirectory=connector_extension_wordpress +odoo-addon-connector_woocommerce@git+https://github.com/nuobit/odoo-addons.git@refs/pull/874/head#subdirectory=connector_woocommerce