mage-os / module-automatic-translation

mage-os/module-automatic-translation

Automatic AI content translation for Mage-OS.

  • Samuele Martini
  • Davide Lunardon
magento2-module Compatibility: 2.4.7, 2.4.9 Code Quality: Fail Tests: N/A Security: Pass MIT

MageOS Automatic Translation Module for Magento

Overview

The MageOS Automatic Translation module allows you to automatically translate content in your Magento store, such as products, categories, pages, and static blocks, using AI-based translation engines. The module is natively integrated with DeepL, OpenAI and Google Gemini, but it can be easily extended to support other translation engines.

Installation

  1. Install the module via Composer:

    composer require mage-os/module-automatic-translation
    
  2. Enable the module:

    bin/magento module:enable MageOS_AutomaticTranslation
    
  3. Run the setup upgrade command:

    bin/magento setup:upgrade
    

Features

Product Translation

The product translation process is divided into two parts:

  1. Textual attributes – The translated value is directly set in the product entity.
  2. Select and Multiselect attributes – The translation of these attributes involves translating the labels of the options, not the option IDs, as option IDs remain consistent across languages.

The module automatically translates products via scheduled cron jobs for both textual and select/multiselect attributes. You can also manually translate products through a backoffice button available in the product editing page.

Cron Jobs for Product Translation:

  • The product translation process runs according to a cron schedule, which can be configured via the Product translation cron expression in the configuration.
  • For select/multiselect attribute options, another cron job is scheduled, configurable via the Select attributes translation cron expression.

Category Translation

Categories are translated only manually via a backoffice button. This is because the number of categories is usually much smaller than the number of products, and thus the manual translation process is more efficient.

For categories, only the following fields are translated:

  • Name
  • Description
  • URL Key
  • Meta information

Note: If you add custom attributes to categories programmatically, it is the developer’s responsibility to decide whether to translate these attributes and add them to the translation list programmatically.

Pages and Static Blocks Translation

Similar to categories, pages and static blocks can only be translated manually via a backoffice button. However, because Magento does not support multiple language versions for pages and static blocks, translation will overwrite the original content when saving. To prevent losing the original content, it is recommended to use the "Save & Duplicate" feature in the backoffice to create a copy of the page or block before translating it.

Retranslation of Products

When the module translates a product for a storeview, it values two attributes specific to that product and that storeview: "skip translation" set to "yes" and "last translation date" with the date of the translation. These attributes are automatically created by the module during installation and are updated each time the product is translated.

This process is used to "flag" the product as "already translated" preventing it from being translated again in future executions, thus improving performance.

However, if the merchant changes the basic content of the product after translation, it may need to be retranslated. The merchant can do this manually by using the button in the backoffice or by setting the "skip translation" attribute to "no" and saving the product. These operations are feasible if there are few products to be edited.

If, however, there are many products to be retranslated or the underlying content changes frequently, it may be useful to enable automatic retranslation. When enabled, this feature also includes products with the "skip translation" attribute set to "yes" in the translation process if the date in the "last translation date" attribute is older than a specified number of days, which can be configured in the settings.

Translation Engines

  • DeepL, OpenAI and Google Gemini are the supported engines by default. You can easily extend the module to support additional translation engines by creating a class that implements the MageOS\AutomaticTranslation\Api\TranslatorInterface.
  • The engine is selected under Stores > Configuration > MageOS > Automatic translation with AI > Translation engine.

Configuration Options

The module provides several configuration options under Stores > Configuration > Services > AI Integration > Automatic translation with AI:

General Configuration

  • Enable: Enables or disables the module. This setting is configurable per store view, allowing you to translate only certain languages.
  • Source Language: Defines the source language of your content. This is typically set to the language in which your products were initially created.
  • Destination Language: This is the target language for translation, which corresponds to the store view's language.

Catalog Translation Options

  • Product Text Attributes to Translate: Select the textual attributes you want to translate (e.g., name, description).
  • Product Select/Multiselect Attributes to Translate: Select which select/multiselect attributes to translate.
  • Translate Disabled Products: Skips disabled products during translation to improve performance.
  • Product Translation Cron Expression: Schedules the product translation process.
  • Select Attributes Translation Cron Expression: Schedules the translation of select/multiselect attributes.
  • Enable Periodic Retranslation & Retranslation Period (in days): Enables automatic retranslation for products if their translation is outdated (older than a set number of days).

Translation Engine Configuration

  • Engine: Choose the translation engine (DeepL or OpenAI or Google Gemini).
  • API Credentials: Configure API credentials for the selected engine.
  • Model Language (for OpenAI & Google Gemini): This field is dynamic and will be populated once valid API credentials are entered.

Adding Additional Translation Engines

To add a new translation engine, you need to:

  1. Create a class implementing MageOS\AutomaticTranslation\Api\TranslatorInterface.
  2. Extend the module to add the new engine's API configuration in system.xml.
  3. Add an after plugin to modify the list of selectable engines in \MageOS\AutomaticTranslation\Model\Config\Source\TranslationEngineList::toOptionArray.

Automatic Translation

[2.1.2] - 21/04/2026

Fixed

  • PHP 8.4 and 8.5 compatibility
  • Hardened preg_replace return value handling in admin before-save plugins (strtolower(null) becomes a TypeError in PHP 8.5)
  • Cast DOMDocument::saveHTML() results to string before passing to html_entity_decode() (PHP 8.5 stricter scalar type enforcement)
  • Cast retranslation period to int before building DateTime::modify() string to avoid DateMalformedStringException in PHP 8.5 when the config value is empty
  • Cast legacy scope value to string before re-encryption in MigrateConfigPaths data patch
  • Cast nullable values to string/int before using as array index (PHP 8.5 null array key deprecation)

Changed

  • Allowed PHP range widened to >=8.2 <8.6 in composer.json

[2.1.0] - 20/03/2026

Changed

  • Minimum PHP version lowered from 8.3 to 8.2
  • Removed typed constants (PHP 8.3 feature) for 8.2 compatibility

[2.0.2] - 20/03/2026

Fixed

  • Fixed CMS page plain text fields (title, heading, meta title, meta keywords, meta description) not being translated
  • Added URL key (identifier) to CMS page translatable fields
  • Fixed URL key slug sanitization using correct field name (identifier instead of url_key)
  • Fixed TranslateParsedContent for string input: translates text before handling widget directives

[2.0.1] - 20/03/2026

Fixed

  • Fixed product translate button passing null instead of 0 to isEnable() for default store

[2.0.0] - 12/03/2026

Changed

  • BREAKING: Minimum PHP version raised to 8.3
  • Constructor promotion across all classes
  • Typed constants (const string, const array, const int) across all classes
  • Modern PHP 8.0+ functions: str_contains, str_starts_with, str_ends_with replacing legacy equivalents
  • Non-capturing catch blocks where exception variable is unused
  • Explicit return types on all methods
  • Union types and mixed type hints where appropriate
  • First-class callable syntax replacing array-style callables
  • Replaced empty() checks on typed nullable properties with explicit null comparisons
  • Changed private methods/properties to protected for Magento interceptor compatibility
  • Replaced inline FQCNs with use imports for exceptions
  • General code cleanup and refactoring

[1.11.2] - 12/03/2026

Fixed

  • Fixed widget content_settings translation using JSON decode/encode instead of unreliable regex on raw encoded string
  • Added translation of repeatable items (title, content, button, image_alt) inside content_settings
  • Added translation of widget preview HTML inside content_settings for Page Builder editor consistency

[1.11.1] - 12/03/2026

Fixed

  • Fixed encodePageBuilderHtmlBox corrupting text/heading content types (double HTML-encoding, style block encoding, spurious newlines)
  • Expanded parsePageBuilderHtmlBox XPath to extract text from text and heading content types, not just html
  • Fixed is_string branch sending entire structural HTML to translator — now only translates widget parameters
  • Fixed log message not showing exception details (sprintf instead of __())

[1.11.0] - 11/03/2026

Fixed

  • Fixed chunking fallback for segments without block-level HTML tags (hard split on sentence/word boundaries)

Added

  • Widget directives are now excluded from translation payload and their translatable parameters are translated individually

[1.10.1] - 10/03/2026

Fixed

  • Fixed translation failing on long texts by adding chunking plugin for translation API limits
  • Fixed double-encoding of HTML entities in PageBuilder HTML Code blocks
  • Fixed greedy string replacement corrupting content when identical text appeared multiple times
  • Fixed DOMDocument corrupting Widget content_settings JSON attributes during translation

[1.10.0] - 05/03/2026

Changed

  • Retry DeepL translation with 2-char target language only on deprecated target language error
  • Updated popup behaviour
  • Extracted parsed content translation to service, reducing code duplication
  • Removed unnecessary dependency on PageBuilder module
  • Loosened dependency constraints in composer.json

[1.9.1] - 14/10/2025

Fixed

  • Fixed product and category translation buttons appearing when translation is disabled

[1.9.0] - 10/10/2025

Fixed

  • Fixed php 8.4 compatibility by @dadolun95 in #34
  • Fixed code standards issues by @rhoerr in #38 and @SamueleMartini in #30 and #35
  • Changed date formatting by @SamueleMartini in #32
  • Feature/config modifications by @SamueleMartini in #33
  • Code refactoring by @dadolun95 in #36
  • Improved README.md by @SamueleMartini in #37

[1.8.1] - 19/02/2025

Fixed

  • Changed product and category buttons to 'secondary' actions and fixed button visualization on category adminhtml form page

[1.8.0] - 19/02/2025

Fixed

  • Fixed configurable products translation made from adminhtml

[1.7.1] - 11/02/2025

Fixed

  • Fixed url rewrite generation after url key translation in translation via cron job

[1.7.0] - 10/02/2025

Added

  • Updated minimum version of the OpenAI SDK to accommodate the new format of the APIs response
  • Translated product attributes only if they are not empty, to save calls and avoid incorrect engine responses
  • Improved prompt for translation with OpenAI
  • Skipped translation of empty attributes when translating from admin panel

[1.6.0] - 16/12/2024

Fixed

  • Added url rewrite generation after url translation in automatic procedure

[1.5.1] - 16/12/2024

Fixed

  • Restored translate button for store as primary
  • Fix Google Gemini prompt

[1.5.0] - 14/12/2024

Added

  • Product gallery images alt text translation

[1.4.0] - 13/12/2024

Added

  • Translate button as secondary type in product and category edit form
  • Uncheck instructions as an attribute note instead of in the label

[1.3.0] - 30/11/2024

Added

  • CHANGELOG file
  • Better filtering of attributes to translate

Removed

  • Mandatory of 'Product select/multiselect attributes to translate' in the system.xml
  • Some variables and constants not used

[1.2.1] - 25/11/2024

Fixed

  • Fixed product saving from admin panel, which did not remove “use default” checkmark automatically

[1.2.0] - 22/11/2024

Changed

  • Updated readme with Google Gemini

[1.1.3] - 19/11/2024

Changed

  • Adjusted composer.json

[1.1.2] - 15/11/2024

Changed

  • Update to 1.1.2 version

[1.1.1] - 15/11/2024

Fixed

  • Fix some instructions

[1.1.0] - 15/11/2024

Added

  • Implemented use of project id in OpenAI integration

[1.0.1] - 15/11/2024

Fixed

  • Fixed parsing of OpenAI response for model list

[1.0.0] - 15/10/2024

Added

  • First module version
Versions
Version Stability QA Status Compatibility Released
2.1.2 stable Fail Magento 2.4.7, 2.4.9 Details 2026-04-30 01:52:12
2.1.1 stable Not tested Not yet tested Details 2026-04-15 21:24:55
2.1.0 stable Not tested Not yet tested Details 2026-03-20 09:13:54
2.0.2 stable Not tested Not yet tested Details 2026-03-19 10:16:16
2.0.1 stable Not tested Not yet tested Details 2026-03-13 16:00:55
2.0.0 stable Not tested Not yet tested Details 2026-03-12 22:33:58
1.11.2 stable Not tested Not yet tested Details 2026-03-12 17:03:32
1.11.1 stable Not tested Not yet tested Details 2026-03-12 13:36:24
1.11.0 stable Not tested Not yet tested Details 2026-03-12 09:00:47
1.10.1 stable Not tested Not yet tested Details 2026-03-11 15:58:19
1.10.0 stable Not tested Not yet tested Details 2026-03-09 11:10:51
1.9.1 stable Not tested Not yet tested Details 2025-10-14 13:03:45
1.9.0 stable Not tested Not yet tested Details 2025-10-10 08:31:14
1.8.1 stable Not tested Not yet tested Details 2025-02-19 05:35:16
1.8.0 stable Not tested Not yet tested Details 2025-02-19 05:06:03
1.7.1 stable Not tested Not yet tested Details 2025-02-11 13:52:48
1.7.0 stable Not tested Not yet tested Details 2025-02-10 20:46:47
1.6.0 stable Not tested Not yet tested Details 2025-01-16 23:33:44
1.5.1 stable Not tested Not yet tested Details 2024-12-16 15:23:30
1.5.0 stable Not tested Not yet tested Details 2024-12-14 16:09:18
1.4.0 stable Not tested Not yet tested Details 2024-12-13 14:10:09
1.3.0 stable Not tested Not yet tested Details 2024-12-03 12:46:12
1.2.1 stable Not tested Not yet tested Details 2024-11-26 11:49:55
1.2.0 stable Not tested Not yet tested Details 2024-11-22 15:56:17
1.1.3 stable Not tested Not yet tested Details 2024-11-19 15:58:17
1.1.2 stable Not tested Not yet tested Details 2024-11-15 14:47:11
1.1.1 stable Not tested Not yet tested Details 2024-11-15 13:28:40
1.1.0 stable Not tested Not yet tested Details 2024-11-15 12:09:13
1.0.1 stable Not tested Not yet tested Details 2024-11-15 11:49:27
1.0.0 stable Not tested Not yet tested Details 2024-11-15 08:04:59

Requires 7

Package Constraint
php >=8.2 <8.6
magento/framework *
magento/module-catalog ^104.0.0
deeplcom/deepl-php ^1
openai-php/client ^0
google-gemini-php/client ^1
guzzlehttp/guzzle ^7.9

Compatibility

Each Magento release line is installed on its supported PHP versions, then the module is built (DI compilation + static-content deploy) and its unit and integration suites are run. The matrix shows the lines and PHP versions the module is confirmed to install and run on. Code-quality results further down (phpstan, phpcs, …) are reported separately and never affect compatibility.

Compatibility matrix (Magento × PHP)
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 Pass Pass
2.4.8 not tested Pass
2.4.9 Pass Pass

Code Quality

Advisory checks against the module's source. Static analysis runs once across the whole module; PHPStan re-runs per Magento + PHP version because resolvable symbols differ between releases. These NEVER affect the Compatibility badge — a phpcs finding can't make a module incompatible.

Static analysis

Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.

Static analysis results
Tool Status Findings Summary
PHPCS Warning 89 89 warnings (ruleset: Magento2) — 6 auto-fixable with phpcbf
PHPMD Warning 12 12 rule violations (UnusedFormalParameter:6, IfStatementAssignment:2, CyclomaticComplexity:2, NPathComplexity:1, UnusedLocalVariable:1)
Cpd Pass 0
Composer validate Info 1 valid; 1 advisory note (composer validate --strict)

PHPStan

Type-checks the module's PHP against a real Magento install at the configured gate level. Re-runs per Magento and PHP version because resolvable symbols differ between releases. Cell → details modal.

PHPStan results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 32 32
2.4.8 32 32
2.4.9 32 32

Tests

Unit and integration suites, run for each applicable Magento and PHP version. A test failure speaks to the module's behaviour, not its compatibility with a Magento line, so it is reported here separately and never reddens the compatibility matrix.

Unit tests

Unit tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 N/A N/A
2.4.8 N/A N/A
2.4.9 N/A N/A

Integration tests

Integration tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 N/A N/A
2.4.8 N/A N/A
2.4.9 N/A N/A

Security

Security checks run directly against the module: an audit of its declared dependencies for known vulnerabilities (composer audit) and a scan of its source for malware and web-shell signatures. Each runs once. A malware detection fails the version outright.

Security results
Tool Status Findings Summary
Composer audit Pass 0
Malware scan Pass 0
License
MIT
Authors

More from mage-os

View vendor
Make it pay

Turn an existing module into recurring revenue.

If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.