├── view
└── adminhtml
│ ├── web
│ ├── css
│ │ └── deepl-translate.less
│ └── images
│ │ ├── deepl_banner.jpg
│ │ └── deepl_banner_api.jpg
│ ├── layout
│ ├── default.xml
│ ├── cms_block_edit.xml
│ ├── cms_page_edit.xml
│ ├── review_product_edit.xml
│ └── catalog_product_attribute_edit.xml
│ └── ui_component
│ ├── product_form.xml
│ └── category_form.xml
├── registration.php
├── Api
└── TranslatorInterface.php
├── composer.json
├── etc
├── module.xml
├── adminhtml
│ ├── routes.xml
│ └── system.xml
├── di.xml
├── config.xml
└── acl.xml
├── Model
├── System
│ └── Config
│ │ ├── TagHandling.php
│ │ ├── Formality.php
│ │ ├── SplitSentence.php
│ │ ├── Version.php
│ │ ├── BlockFields.php
│ │ ├── PageFields.php
│ │ ├── ProductFields.php
│ │ └── CategoryFields.php
├── Translator
│ ├── Catalog
│ │ ├── Category.php
│ │ ├── Product.php
│ │ └── Attribute.php
│ ├── Cms
│ │ ├── Block.php
│ │ └── Page.php
│ └── Review.php
└── Client
│ └── Deepl.php
├── Controller
└── Adminhtml
│ ├── Cms.php
│ ├── Catalog.php
│ ├── Review.php
│ ├── Catalog
│ ├── Category
│ │ └── Translate.php
│ ├── Product
│ │ └── Translate.php
│ └── Attribute
│ │ └── Translate.php
│ ├── Review
│ └── Translate.php
│ └── Cms
│ ├── Block
│ └── Translate.php
│ └── Page
│ └── Translate.php
├── Block
└── Adminhtml
│ ├── Catalog
│ ├── Product
│ │ └── Edit
│ │ │ └── Button
│ │ │ └── Translate.php
│ ├── Category
│ │ └── Edit
│ │ │ └── Button
│ │ │ └── Translate.php
│ └── Attribute
│ │ └── Edit
│ │ └── TranslateButton.php
│ ├── System
│ └── Config
│ │ └── Fieldset
│ │ └── Info.php
│ ├── Review
│ └── Edit
│ │ └── TranslateButton.php
│ └── Cms
│ ├── Page
│ └── Edit
│ │ └── TranslateButton.php
│ └── Block
│ └── Edit
│ └── TranslateButton.php
├── README.MD
└── Helper
└── Config.php
/view/adminhtml/web/css/deepl-translate.less:
--------------------------------------------------------------------------------
1 | .options-scrollable .dropdown-menu {
2 | max-height: 20vw;
3 | overflow-y: auto;
4 | }
--------------------------------------------------------------------------------
/view/adminhtml/web/images/deepl_banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aromicon/magento2-deepl/HEAD/view/adminhtml/web/images/deepl_banner.jpg
--------------------------------------------------------------------------------
/view/adminhtml/web/images/deepl_banner_api.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aromicon/magento2-deepl/HEAD/view/adminhtml/web/images/deepl_banner_api.jpg
--------------------------------------------------------------------------------
/registration.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Api/TranslatorInterface.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Api;
11 |
12 | interface TranslatorInterface
13 | {
14 | public function translate($string, $sourceLanguage, $targetLanguage);
15 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aromicon/module-deepl",
3 | "description": "Magento 2 Extension for Translation via Deepl API",
4 | "require": {
5 | "php": "~8.1.0|~8.2.0|~8.3.0",
6 | "magento/module-catalog": "*",
7 | "magento/magento-composer-installer": "*"
8 | },
9 | "suggest": {
10 |
11 | },
12 | "type": "magento2-module",
13 | "version": "2.0.0.24",
14 | "license": [
15 |
16 | ],
17 | "autoload": {
18 | "files": [
19 | "registration.php"
20 | ],
21 | "psr-4": {
22 | "Aromicon\\Deepl\\": ""
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/etc/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/etc/adminhtml/routes.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Model/System/Config/TagHandling.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\System\Config;
10 |
11 | class TagHandling implements \Magento\Framework\Option\ArrayInterface
12 | {
13 | /**
14 | * {@inheritdoc}
15 | */
16 | public function toOptionArray()
17 | {
18 | return [
19 | ['value' => 'xml', 'label' => __('XML')],
20 | ['value' => 'html', 'label' => __('HTML')]
21 | ];
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/view/adminhtml/ui_component/product_form.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
18 |
--------------------------------------------------------------------------------
/view/adminhtml/ui_component/category_form.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
18 |
--------------------------------------------------------------------------------
/view/adminhtml/layout/cms_block_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/view/adminhtml/layout/cms_page_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/view/adminhtml/layout/review_product_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Model/System/Config/Formality.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\System\Config;
10 |
11 | class Formality implements \Magento\Framework\Option\ArrayInterface
12 | {
13 | /**
14 | * {@inheritdoc}
15 | */
16 | public function toOptionArray()
17 | {
18 | return [
19 | ['value' => 'default', 'label' => __('Default')],
20 | ['value' => 'more', 'label' => __('More')],
21 | ['value' => 'less', 'label' => __('Less')],
22 | ];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Model/System/Config/SplitSentence.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\System\Config;
10 |
11 | class SplitSentence implements \Magento\Framework\Option\ArrayInterface
12 | {
13 | /**
14 | * {@inheritdoc}
15 | */
16 | public function toOptionArray()
17 | {
18 | return [
19 | ['value' => 1, 'label' => __('Yes')],
20 | ['value' => 0, 'label' => __('No')],
21 | ['value' => 'nonewlines', 'label' => __('No New Lines')],
22 | ];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Model/System/Config/Version.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\System\Config;
10 |
11 | class Version implements \Magento\Framework\Option\ArrayInterface
12 | {
13 | const FREE = 'free';
14 |
15 | const PRO = 'pro';
16 |
17 | /**
18 | * {@inheritdoc}
19 | */
20 | public function toOptionArray()
21 | {
22 | return [
23 | ['value' => self::FREE, 'label' => __('Free')],
24 | ['value' => self::PRO, 'label' => __('Pro')],
25 | ];
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Model/System/Config/BlockFields.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\System\Config;
10 |
11 | class BlockFields implements \Magento\Framework\Option\ArrayInterface
12 | {
13 | /**
14 | * {@inheritdoc}
15 | */
16 | public function toOptionArray()
17 | {
18 | return [
19 | ['value' => 'title', 'label' => __('Page Title')],
20 | ['value' => 'content', 'label' => __('Content')],
21 | ['value' => 'identifier', 'label' => __('URL Key')],
22 | ];
23 | }
24 | }
--------------------------------------------------------------------------------
/view/adminhtml/layout/catalog_product_attribute_edit.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Cms.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Controller\Adminhtml;
10 |
11 | abstract class Cms extends \Magento\Backend\App\Action
12 | {
13 | const ADMIN_RESOURCE = 'Aromicon_Deepl::cms';
14 |
15 | /**
16 | * @var \Magento\Framework\Registry
17 | */
18 | protected $_coreRegistry;
19 |
20 | /**
21 | * @param \Magento\Backend\App\Action\Context $context
22 | * @param \Magento\Framework\Registry $coreRegistry
23 | */
24 | public function __construct(
25 | \Magento\Backend\App\Action\Context $context,
26 | \Magento\Framework\Registry $coreRegistry
27 | ) {
28 | $this->_coreRegistry = $coreRegistry;
29 | parent::__construct($context);
30 | }
31 | }
--------------------------------------------------------------------------------
/Controller/Adminhtml/Catalog.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Controller\Adminhtml;
10 |
11 | abstract class Catalog extends \Magento\Backend\App\Action
12 | {
13 | const ADMIN_RESOURCE = 'Aromicon_Deepl::catalog';
14 |
15 | /**
16 | * @var \Magento\Framework\Registry
17 | */
18 | protected $_coreRegistry;
19 |
20 | /**
21 | * @param \Magento\Backend\App\Action\Context $context
22 | * @param \Magento\Framework\Registry $coreRegistry
23 | */
24 | public function __construct(
25 | \Magento\Backend\App\Action\Context $context,
26 | \Magento\Framework\Registry $coreRegistry
27 | ) {
28 | $this->_coreRegistry = $coreRegistry;
29 | parent::__construct($context);
30 | }
31 | }
--------------------------------------------------------------------------------
/Controller/Adminhtml/Review.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Controller\Adminhtml;
10 |
11 | abstract class Review extends \Magento\Backend\App\Action
12 | {
13 | const ADMIN_RESOURCE = 'Aromicon_Deepl::translate_review';
14 |
15 | /**
16 | * @var \Magento\Framework\Registry
17 | */
18 | protected $_coreRegistry;
19 |
20 | /**
21 | * @param \Magento\Backend\App\Action\Context $context
22 | * @param \Magento\Framework\Registry $coreRegistry
23 | */
24 | public function __construct(
25 | \Magento\Backend\App\Action\Context $context,
26 | \Magento\Framework\Registry $coreRegistry
27 | ) {
28 | $this->_coreRegistry = $coreRegistry;
29 | parent::__construct($context);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Model/System/Config/PageFields.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\System\Config;
10 |
11 | class PageFields implements \Magento\Framework\Option\ArrayInterface
12 | {
13 | /**
14 | * {@inheritdoc}
15 | */
16 | public function toOptionArray()
17 | {
18 | return [
19 | ['value' => 'title', 'label' => __('Page Title')],
20 | ['value' => 'content', 'label' => __('Content')],
21 | ['value' => 'content_heading', 'label' => __('Content Heading')],
22 | ['value' => 'meta_keywords', 'label' => __('Meta Keywords')],
23 | ['value' => 'meta_description', 'label' => __('Meta Description')],
24 | ['value' => 'meta_title', 'label' => __('Meta Title')],
25 | ['value' => 'identifier', 'label' => __('URL Key')],
26 | ];
27 | }
28 | }
--------------------------------------------------------------------------------
/etc/di.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 | - Magento\Framework\Filter\DirectiveProcessor\DependDirective
17 | - Magento\Framework\Filter\DirectiveProcessor\IfDirective
18 | - Magento\Framework\Filter\DirectiveProcessor\TemplateDirective
19 | - Magento\Framework\Filter\DirectiveProcessor\LegacyDirective
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/etc/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 | https://api.deepl.com/v2/
16 | https://api-free.deepl.com/v2/
17 |
18 |
19 | title,content
20 | title,content,content_heading,meta_keywords,meta_description,meta_title,identifier
21 |
22 |
23 | name,short_description,description,meta_title,meta_keywords,meta_description,url_key
24 |
25 |
26 | name,description,meta_title,meta_keywords,meta_description,url_key
27 |
28 |
29 |
30 |
31 |
32 | 1
33 |
34 |
35 | 1
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Model/System/Config/ProductFields.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\System\Config;
10 |
11 | class ProductFields implements \Magento\Framework\Option\ArrayInterface
12 | {
13 | /**
14 | * @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface
15 | */
16 | private $attributeRepository;
17 | /**
18 | * @var \Magento\Framework\Api\SearchCriteriaBuilder
19 | */
20 | private $searchCriteriaBuilder;
21 |
22 | public function __construct(
23 | \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository,
24 | \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
25 | ) {
26 | $this->attributeRepository = $attributeRepository;
27 | $this->searchCriteriaBuilder = $searchCriteriaBuilder;
28 | }
29 |
30 | /**
31 | * {@inheritdoc}
32 | */
33 | public function toOptionArray()
34 | {
35 | $options = [];
36 | $filter = $this->searchCriteriaBuilder
37 | ->addFilter('frontend_input', ['text','textarea'], 'in')
38 | ->addFilter('is_global', 0)
39 | ->create();
40 | $textAttributes = $this->attributeRepository->getList($filter)->getItems();
41 |
42 | foreach ($textAttributes as $attribute) {
43 | $options[] = [
44 | 'value' => $attribute->getAttributeCode(),
45 | 'label' => $attribute->getFrontendLabel()
46 | ];
47 | }
48 |
49 | return $options;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Model/System/Config/CategoryFields.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\System\Config;
10 |
11 | class CategoryFields implements \Magento\Framework\Option\ArrayInterface
12 | {
13 | /**
14 | * @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface
15 | */
16 | private $attributeRepository;
17 | /**
18 | * @var \Magento\Framework\Api\SearchCriteriaBuilder
19 | */
20 | private $searchCriteriaBuilder;
21 |
22 | public function __construct(
23 | \Magento\Catalog\Api\CategoryAttributeRepositoryInterface $attributeRepository,
24 | \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
25 | ) {
26 | $this->attributeRepository = $attributeRepository;
27 | $this->searchCriteriaBuilder = $searchCriteriaBuilder;
28 | }
29 |
30 | /**
31 | * {@inheritdoc}
32 | */
33 | public function toOptionArray()
34 | {
35 | $options = [];
36 | $filter = $this->searchCriteriaBuilder
37 | ->addFilter('frontend_input', ['text','textarea'], 'in')
38 | ->addFilter('is_global', 0)
39 | ->create();
40 | $textAttributes = $this->attributeRepository->getList($filter)->getItems();
41 |
42 | foreach ($textAttributes as $attribute) {
43 | $options[] = [
44 | 'value' => $attribute->getAttributeCode(),
45 | 'label' => $attribute->getFrontendLabel()
46 | ];
47 | }
48 |
49 | return $options;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/etc/acl.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Catalog/Category/Translate.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Controller\Adminhtml\Catalog\Category;
11 |
12 | use Magento\Framework\Exception\LocalizedException;
13 |
14 | class Translate extends \Aromicon\Deepl\Controller\Adminhtml\Catalog
15 | {
16 |
17 | const ADMIN_RESOURCE = 'Aromicon_Deepl::translate_category';
18 |
19 | /**
20 | * @var \Aromicon\Deepl\Model\Translator\Catalog\Category
21 | */
22 | private $categoryTranslator;
23 |
24 | /**
25 | * Translate constructor.
26 | * @param \Magento\Backend\App\Action\Context $context
27 | * @param \Magento\Framework\Registry $coreRegistry
28 | * @param \Aromicon\Deepl\Model\Translator\Catalog\Category $categoryTranslator
29 | */
30 | public function __construct(
31 | \Magento\Backend\App\Action\Context $context,
32 | \Magento\Framework\Registry $coreRegistry,
33 | \Aromicon\Deepl\Model\Translator\Catalog\Category $categoryTranslator
34 | ) {
35 | $this->categoryTranslator = $categoryTranslator;
36 | parent::__construct($context, $coreRegistry);
37 | }
38 |
39 | /**
40 | * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void
41 | */
42 | public function execute()
43 | {
44 | $categoryId = $this->getRequest()->getParam('category_id');
45 | $store = $this->getRequest()->getParam('store');
46 |
47 | try {
48 | $this->categoryTranslator->translateAndCopy($categoryId, $store);
49 | } catch (\Exception $e) {
50 | $this->messageManager->addErrorMessage(__('Category couldn\'t be translated. %1', $e->getMessage()));
51 | }
52 |
53 | $this->_redirect('catalog/category/edit', ['id' => $categoryId]);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Catalog/Product/Translate.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Controller\Adminhtml\Catalog\Product;
11 |
12 | use Magento\Framework\Exception\LocalizedException;
13 |
14 | class Translate extends \Aromicon\Deepl\Controller\Adminhtml\Catalog
15 | {
16 | const ADMIN_RESOURCE = 'Aromicon_Deepl::translate_product';
17 | /**
18 | * @var \Aromicon\Deepl\Model\Translator\Catalog\Product
19 | */
20 | private $productTranslator;
21 |
22 | /**
23 | * Translate constructor.
24 | * @param \Magento\Backend\App\Action\Context $context
25 | * @param \Magento\Framework\Registry $coreRegistry
26 | * @param \Aromicon\Deepl\Model\Translator\Catalog\Product $productTranslator
27 | */
28 | public function __construct(
29 | \Magento\Backend\App\Action\Context $context,
30 | \Magento\Framework\Registry $coreRegistry,
31 | \Aromicon\Deepl\Model\Translator\Catalog\Product $productTranslator
32 | ) {
33 | $this->productTranslator = $productTranslator;
34 | parent::__construct($context, $coreRegistry);
35 | }
36 |
37 | /**
38 | * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void
39 | */
40 | public function execute()
41 | {
42 | $productId = $this->getRequest()->getParam('product_id');
43 | $store = $this->getRequest()->getParam('store');
44 |
45 | try {
46 | $this->productTranslator->translateAndCopy($productId, $store);
47 | } catch (\Exception $e) {
48 | $this->messageManager->addErrorMessage(__('Product couldn\'t be translated. %1', $e->getMessage()));
49 | }
50 |
51 | $this->messageManager->addSuccessMessage(__('Product was translated successfully'));
52 | $this->_redirect('catalog/product/edit', ['id' => $productId]);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Review/Translate.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Controller\Adminhtml\Review;
11 |
12 | use Magento\Framework\Controller\ResultFactory;
13 |
14 | class Translate extends \Aromicon\Deepl\Controller\Adminhtml\Review
15 | {
16 |
17 | const ADMIN_RESOURCE = 'Aromicon_Deepl::translate_review';
18 |
19 | /** @var \Aromicon\Deepl\Model\Translator\Review */
20 | protected $reviewTranslator;
21 |
22 | /**
23 | * Translate constructor.
24 | * @param \Magento\Backend\App\Action\Context $context
25 | * @param \Magento\Framework\Registry $coreRegistry
26 | * @param \Aromicon\Deepl\Model\Translator\Review $reviewTranslator
27 | */
28 | public function __construct(
29 | \Magento\Backend\App\Action\Context $context,
30 | \Magento\Framework\Registry $coreRegistry,
31 | \Aromicon\Deepl\Model\Translator\Review $reviewTranslator
32 | ) {
33 | $this->reviewTranslator = $reviewTranslator;
34 | parent::__construct($context, $coreRegistry);
35 | }
36 |
37 | /**
38 | * @return \Magento\Backend\Model\View\Result\Redirect|\Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
39 | */
40 | public function execute()
41 | {
42 | $reviewId = $this->getRequest()->getParam('review_id');
43 | $store = $this->getRequest()->getParam('store');
44 |
45 | try {
46 | $this->reviewTranslator->translateAndCopy($reviewId, $store);
47 | } catch (\Exception $e) {
48 | $this->messageManager->addErrorMessage(__('Review couldn\'t be translated'));
49 | }
50 |
51 | /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
52 | $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
53 | return $resultRedirect->setPath('review/product/');
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Catalog/Attribute/Translate.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Controller\Adminhtml\Catalog\Attribute;
11 |
12 | use Magento\Framework\Controller\ResultFactory;
13 | use Magento\Framework\Exception\LocalizedException;
14 |
15 | class Translate extends \Aromicon\Deepl\Controller\Adminhtml\Catalog
16 | {
17 |
18 | const ADMIN_RESOURCE = 'Aromicon_Deepl::translate_attribute';
19 |
20 | /**
21 | * @var \Aromicon\Deepl\Model\Translator\Catalog\Attribute
22 | */
23 | private $attributeTranslator;
24 |
25 | /**
26 | * Translate constructor.
27 | * @param \Magento\Backend\App\Action\Context $context
28 | * @param \Magento\Framework\Registry $coreRegistry
29 | * @param \Aromicon\Deepl\Model\Translator\Catalog\Attribute $attributeTranslator
30 | */
31 | public function __construct(
32 | \Magento\Backend\App\Action\Context $context,
33 | \Magento\Framework\Registry $coreRegistry,
34 | \Aromicon\Deepl\Model\Translator\Catalog\Attribute $attributeTranslator
35 | ) {
36 | $this->attributeTranslator = $attributeTranslator;
37 | parent::__construct($context, $coreRegistry);
38 | }
39 |
40 | /**
41 | * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void
42 | */
43 | public function execute()
44 | {
45 | $attributeId = $this->getRequest()->getParam('attribute_id');
46 | $store = $this->getRequest()->getParam('store');
47 |
48 | try {
49 | $this->attributeTranslator->translateAndCopy($attributeId, $store);
50 | } catch (\Exception $e) {
51 | $this->messageManager->addErrorMessage(__('Attribute couldn\'t be translated. %1', $e->getMessage()));
52 | }
53 |
54 | $this->_redirect('catalog/product_attribute/edit', ['attribute_id' => $attributeId]);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Cms/Block/Translate.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Controller\Adminhtml\Cms\Block;
11 |
12 | use Magento\Framework\Controller\ResultFactory;
13 |
14 | class Translate extends \Aromicon\Deepl\Controller\Adminhtml\Cms
15 | {
16 | const ADMIN_RESOURCE = 'Aromicon_Deepl::translate_block';
17 |
18 | /**
19 | * @var \Aromicon\Deepl\Model\Translator\Cms\Block
20 | */
21 | private $cmsTranslator;
22 |
23 | /**
24 | * Translate constructor.
25 | * @param \Magento\Backend\App\Action\Context $context
26 | * @param \Magento\Framework\Registry $coreRegistry
27 | * @param \Aromicon\Deepl\Model\Translator\Cms\Block $cmsTranslator
28 | */
29 | public function __construct(
30 | \Magento\Backend\App\Action\Context $context,
31 | \Magento\Framework\Registry $coreRegistry,
32 | \Aromicon\Deepl\Model\Translator\Cms\Block $cmsTranslator
33 | ) {
34 | $this->cmsTranslator = $cmsTranslator;
35 | parent::__construct($context, $coreRegistry);
36 | }
37 |
38 | /**
39 | * @return \Magento\Backend\Model\View\Result\Redirect|\Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
40 | */
41 | public function execute()
42 | {
43 | $blockId = $this->getRequest()->getParam('block_id');
44 | $store = $this->getRequest()->getParam('store');
45 |
46 | try {
47 | $this->cmsTranslator->translateAndCopy($blockId, $store);
48 | $this->messageManager->addSuccessMessage(__('Block "%1" was copied & translated to Store %2.', $blockId, $store));
49 | } catch (\Exception $e) {
50 | $this->messageManager->addErrorMessage(__('Block couldn\'t be translated. %1', $e->getMessage()));
51 | }
52 |
53 | /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
54 | $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
55 | return $resultRedirect->setPath('cms/block/');
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Cms/Page/Translate.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Controller\Adminhtml\Cms\Page;
11 |
12 | use Magento\Framework\Controller\ResultFactory;
13 | use Magento\Framework\Exception\LocalizedException;
14 |
15 | class Translate extends \Aromicon\Deepl\Controller\Adminhtml\Cms
16 | {
17 |
18 | const ADMIN_RESOURCE = 'Aromicon_Deepl::translate_page';
19 |
20 | /**
21 | * @var \Aromicon\Deepl\Model\Translator\Cms\Page
22 | */
23 | protected $cmsTranslator;
24 |
25 | /**
26 | * Translate constructor.
27 | * @param \Magento\Backend\App\Action\Context $context
28 | * @param \Magento\Framework\Registry $coreRegistry
29 | * @param \Aromicon\Deepl\Model\Translator\Cms\Page $cmsTranslator
30 | */
31 | public function __construct(
32 | \Magento\Backend\App\Action\Context $context,
33 | \Magento\Framework\Registry $coreRegistry,
34 | \Aromicon\Deepl\Model\Translator\Cms\Page $cmsTranslator
35 | ) {
36 | $this->cmsTranslator = $cmsTranslator;
37 | parent::__construct($context, $coreRegistry);
38 | }
39 |
40 | /**
41 | * @return \Magento\Backend\Model\View\Result\Redirect|\Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
42 | */
43 | public function execute()
44 | {
45 | $pageId = $this->getRequest()->getParam('page_id');
46 | $store = $this->getRequest()->getParam('store');
47 |
48 | try {
49 | $this->cmsTranslator->translateAndCopy($pageId, $store);
50 | $this->messageManager->addSuccessMessage(__('Page "%1" was copied & translated to Store %2.', $pageId, $store));
51 | } catch (LocalizedException $e) {
52 | $this->messageManager->addErrorMessage(__('Page couldn\'t be translated. %1', $e->getMessage()));
53 | }
54 |
55 | /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
56 | $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
57 | return $resultRedirect->setPath('cms/page/');
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Model/Translator/Catalog/Category.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\Translator\Catalog;
10 |
11 | class Category
12 | {
13 | /**
14 | * @var \Magento\Catalog\Api\CategoryRepositoryInterface
15 | */
16 | private $categoryRepository;
17 |
18 | /**
19 | * @var \Aromicon\Deepl\Api\TranslatorInterface
20 | */
21 | private $translator;
22 |
23 | /**
24 | * @var \Aromicon\Deepl\Helper\Config
25 | */
26 | private $config;
27 |
28 | private $categoryResource;
29 |
30 | public function __construct(
31 | \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository,
32 | \Aromicon\Deepl\Api\TranslatorInterface $translator,
33 | \Aromicon\Deepl\Helper\Config $config,
34 | \Magento\Catalog\Model\ResourceModel\Category $categoryResource
35 | ) {
36 | $this->categoryRepository = $categoryRepository;
37 | $this->translator = $translator;
38 | $this->config = $config;
39 | $this->categoryResource = $categoryResource;
40 | }
41 |
42 | /**
43 | * @param $productId int
44 | * @param $fromStoreId int
45 | * @param $toStoreId int
46 | * @throws \Magento\Framework\Exception\LocalizedException
47 | */
48 | public function translateAndCopy($categoryId, $toStoreId)
49 | {
50 | $sourceCategory = $this->categoryRepository->get($categoryId, $this->config->getSourceStoreId($toStoreId));
51 | $category = $this->categoryRepository->get($categoryId, $toStoreId);
52 |
53 | $sourceLanguage = $this->config->getSourceLanguage($toStoreId);
54 | $targetLanguage = $this->config->getLanguageCodeByStoreId($toStoreId, true);
55 |
56 | $categoryFields = $this->config->getTranslatableCategoryFields();
57 |
58 | foreach ($categoryFields as $field) {
59 | if ($sourceCategory->getData($field) == '') {
60 | continue;
61 | }
62 |
63 | $translatedText = $this->translator
64 | ->translate($sourceCategory->getData($field), $sourceLanguage, $targetLanguage);
65 |
66 | if ($category->getData($field) == $translatedText) {
67 | continue;
68 | }
69 |
70 | $category->setData($field, $translatedText);
71 | $this->categoryResource->saveAttribute($category, $field);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Model/Translator/Catalog/Product.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\Translator\Catalog;
10 |
11 | class Product
12 | {
13 | /**
14 | * @var \Magento\Catalog\Api\ProductRepositoryInterface
15 | */
16 | private $productRepository;
17 |
18 | /**
19 | * @var \Aromicon\Deepl\Api\TranslatorInterface
20 | */
21 | private $translator;
22 |
23 | /**
24 | * @var \Aromicon\Deepl\Helper\Config
25 | */
26 | private $config;
27 |
28 | private $productResource;
29 |
30 | public function __construct(
31 | \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
32 | \Aromicon\Deepl\Api\TranslatorInterface $translator,
33 | \Aromicon\Deepl\Helper\Config $config,
34 | \Magento\Catalog\Model\ResourceModel\Product $productResource
35 | ) {
36 | $this->productRepository = $productRepository;
37 | $this->translator = $translator;
38 | $this->config = $config;
39 | $this->productResource = $productResource;
40 | }
41 |
42 | /**
43 | * @param $productId int
44 | * @param $fromStoreId int
45 | * @param $toStoreId int
46 | * @throws \Magento\Framework\Exception\LocalizedException
47 | * @throws \Exception
48 | */
49 | public function translateAndCopy($productId, $toStoreId)
50 | {
51 | $sourceProduct = $this->productRepository->getById($productId, true, $this->config->getSourceStoreId($toStoreId));
52 | $product = $this->productRepository->getById($productId, true, $toStoreId);
53 |
54 | $sourceLanguage = $this->config->getSourceLanguage($toStoreId);
55 | $targetLanguage = $this->config->getLanguageCodeByStoreId($toStoreId, true);
56 |
57 | $pageFields = $this->config->getTranslatableProductFields();
58 |
59 | foreach ($pageFields as $field) {
60 | if ($sourceProduct->getData($field) == '') {
61 | continue;
62 | }
63 |
64 | $translatedText = $this->translator
65 | ->translate($sourceProduct->getData($field), $sourceLanguage, $targetLanguage);
66 |
67 | if ($product->getData($field) == $translatedText) {
68 | continue;
69 | }
70 |
71 | $product->setData($field, $translatedText);
72 | $this->productResource->saveAttribute($product, $field);
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Catalog/Product/Edit/Button/Translate.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Block\Adminhtml\Catalog\Product\Edit\Button;
10 |
11 | use Magento\Framework\Registry;
12 | use Magento\Framework\View\Element\UiComponent\Context;
13 | use Magento\Ui\Component\Control\Container;
14 | use Magento\Framework\AuthorizationInterface;
15 |
16 | /**
17 | * Class Save
18 | */
19 | class Translate extends \Magento\Catalog\Block\Adminhtml\Product\Edit\Button\Generic
20 | {
21 | private $authorization;
22 | private $storeManagement;
23 | private $config;
24 |
25 | public function __construct(
26 | Context $context,
27 | Registry $registry,
28 | \Aromicon\Deepl\Helper\Config $config,
29 | \Magento\Store\Model\StoreManagerInterface $storeManagement,
30 | AuthorizationInterface $authorization
31 | ) {
32 | $this->config = $config;
33 | $this->storeManagement = $storeManagement;
34 | $this->authorization = $authorization;
35 | parent::__construct($context, $registry);
36 | }
37 |
38 | /**
39 | * {@inheritdoc}
40 | */
41 | public function getButtonData()
42 | {
43 | if ($this->getProduct()->isReadonly()
44 | || !$this->config->hasApiKey()
45 | || !$this->authorization->isAllowed('Aromicon_Deepl::translate_product')) {
46 | return [];
47 | }
48 |
49 | return [
50 | 'label' => __('Translate'),
51 | 'class' => 'save options-scrollable',
52 | 'class_name' => Container::SPLIT_BUTTON,
53 | 'options' => $this->getOptions(),
54 | ];
55 | }
56 |
57 | /**
58 | * Retrieve options
59 | *
60 | * @return array
61 | */
62 | protected function getOptions()
63 | {
64 | $stores = $this->storeManagement->getStores();
65 | foreach ($stores as $store) {
66 | $options[] = [
67 | 'label' => __($store->getName().' '.$this->config->getStoreLanguage($store)),
68 | 'onclick' => sprintf("location.href = '%s';", $this->getUrl('aromicon_deepl/catalog_product/translate', [
69 | 'product_id' => $this->getProduct()->getId(),
70 | 'store' => $store->getId()
71 | ]
72 | )),
73 | ];
74 | }
75 |
76 | return $options;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Block/Adminhtml/System/Config/Fieldset/Info.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Block\Adminhtml\System\Config\Fieldset;
10 |
11 | use Magento\Config\Block\System\Config\Form\Fieldset;
12 |
13 | /**
14 | * Fieldset renderer with url attached to comment.
15 | */
16 | class Info extends Fieldset
17 | {
18 | private $config;
19 | private $client;
20 |
21 | public function __construct(
22 | \Magento\Backend\Block\Context $context,
23 | \Magento\Backend\Model\Auth\Session $authSession,
24 | \Magento\Framework\View\Helper\Js $jsHelper,
25 | \Aromicon\Deepl\Helper\Config $config,
26 | \Aromicon\Deepl\Model\Client\Deepl $client,
27 | array $data = []
28 | ) {
29 | $this->config = $config;
30 | $this->client = $client;
31 | parent::__construct($context, $authSession, $jsHelper, $data);
32 | }
33 |
34 | /**
35 | * @inheritdoc
36 | */
37 | protected function _getHeaderCommentHtml($element)
38 | {
39 |
40 | if ($this->config->getDeeplApiKey()) {
41 | $comment = '
42 |
43 |
44 |
45 | ';
46 | if ($this->client->isValid()) {
47 | $comment .= __('Character Count: %1
', $this->client->getCharacterCount());
48 | $comment .= __('Character Limit: %1
', $this->client->getCharacterLimit());
49 | } else {
50 | $comment .= __('Authorization failed. Please check your API Key.
');
51 | }
52 | $element->setComment($comment);
53 | } else {
54 | $comment = '
55 |
56 |
57 |
58 | ';
59 | $comment .= __('No API Key provided
');
60 | $element->setComment($comment);
61 | }
62 |
63 | return parent::_getHeaderCommentHtml($element);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Catalog/Category/Edit/Button/Translate.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Block\Adminhtml\Catalog\Category\Edit\Button;
10 |
11 | use Magento\Ui\Component\Control\Container;
12 | use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
13 | use Magento\Catalog\Block\Adminhtml\Category\AbstractCategory;
14 | use Magento\Framework\AuthorizationInterface;
15 |
16 | /**
17 | * Class Translate
18 | */
19 | class Translate extends AbstractCategory implements ButtonProviderInterface
20 | {
21 | private $authorization;
22 | private $storeManagement;
23 | private $config;
24 |
25 | public function __construct(
26 | \Magento\Backend\Block\Template\Context $context,
27 | \Magento\Catalog\Model\ResourceModel\Category\Tree $categoryTree,
28 | \Magento\Framework\Registry $registry,
29 | \Magento\Catalog\Model\CategoryFactory $categoryFactory,
30 | \Aromicon\Deepl\Helper\Config $config,
31 | \Magento\Store\Model\StoreManagerInterface $storeManagement,
32 | AuthorizationInterface $authorization,
33 | array $data = []
34 | ) {
35 | $this->config = $config;
36 | $this->storeManagement = $storeManagement;
37 | $this->authorization = $authorization;
38 | parent::__construct($context, $categoryTree, $registry, $categoryFactory, $data);
39 | }
40 |
41 | /**
42 | * {@inheritdoc}
43 | */
44 | public function getButtonData()
45 | {
46 | if ($this->getCategory()->isReadonly()
47 | || !$this->config->hasApiKey()
48 | || !$this->authorization->isAllowed('Aromicon_Deepl::translate_category')
49 | ) {
50 | return [];
51 | }
52 |
53 | return [
54 | 'label' => __('Translate'),
55 | 'class' => 'save options-scrollable',
56 | 'class_name' => Container::SPLIT_BUTTON,
57 | 'options' => $this->getOptions(),
58 | ];
59 | }
60 |
61 | /**
62 | * Retrieve options
63 | *
64 | * @return array
65 | */
66 | protected function getOptions()
67 | {
68 | $stores = $this->storeManagement->getStores();
69 | foreach ($stores as $store) {
70 | $options[] = [
71 | 'label' => __($store->getName().' '.$this->config->getStoreLanguage($store)),
72 | 'onclick' => sprintf("location.href = '%s';", $this->getUrl('aromicon_deepl/catalog_category/translate', [
73 | 'category_id' => $this->getCategory()->getId(),
74 | 'store' => $store->getId()
75 | ]
76 | )),
77 | ];
78 | }
79 |
80 | return $options;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Review/Edit/TranslateButton.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Block\Adminhtml\Review\Edit;;
11 |
12 | class TranslateButton extends \Magento\Backend\Block\Widget\Container
13 | {
14 | /**
15 | * @var \Magento\Store\Api\StoreManagementInterface
16 | */
17 | protected $storeManagement;
18 |
19 | /**
20 | * @var \Magento\Framework\Registry
21 | */
22 | protected $coreRegistry;
23 |
24 | /**
25 | * @var \Aromicon\Deepl\Helper\Config
26 | */
27 | protected $config;
28 |
29 | /**
30 | * @param \Magento\Backend\Block\Widget\Context $context
31 | * @param \Magento\Store\Api\StoreManagementInterface $storeManagement
32 | * @param array $data
33 | */
34 | public function __construct(
35 | \Magento\Backend\Block\Widget\Context $context,
36 | \Magento\Framework\Registry $coreRegistry,
37 | \Magento\Store\Model\StoreManagerInterface $storeManagement,
38 | \Aromicon\Deepl\Helper\Config $config,
39 | array $data = []
40 | ) {
41 | $this->storeManagement = $storeManagement;
42 | $this->coreRegistry = $coreRegistry;
43 | $this->config = $config;
44 | parent::__construct($context, $data);
45 | }
46 |
47 | /**
48 | * Prepare button and grid
49 | *
50 | * @return \Magento\Catalog\Block\Adminhtml\Product
51 | */
52 | protected function _prepareLayout()
53 | {
54 | $addButtonProps = [
55 | 'id' => 'translate_review',
56 | 'label' => __('Translate'),
57 | 'class' => 'add options-scrollable',
58 | 'button_class' => 'options-scrollable',
59 | 'class_name' => \Magento\Backend\Block\Widget\Button\SplitButton::class,
60 | 'options' => $this->_getTranslateOptions(),
61 | ];
62 |
63 | if ($this->config->hasApiKey()) {
64 | $this->buttonList->add('translate', $addButtonProps);
65 | }
66 |
67 | return parent::_prepareLayout();
68 | }
69 |
70 | /**
71 | * Retrieve options for 'Add Product' split button
72 | *
73 | * @return array
74 | */
75 | protected function _getTranslateOptions()
76 | {
77 | $splitButtonOptions = [];
78 | $stores = $this->storeManagement->getStores();
79 |
80 | foreach ($stores as $key => $store) {
81 | $splitButtonOptions[$key] = [
82 | 'label' => __($store->getName().' '.$this->config->getStoreLanguage($store)),
83 | 'onclick' => "setLocation('" . $this->_getTranslateUrl($store) . "')"
84 | ];
85 | }
86 |
87 | return $splitButtonOptions;
88 | }
89 |
90 | /**
91 | * Retrieve product create url by specified product type
92 | *
93 | * @param string $type
94 | * @return string
95 | */
96 | protected function _getTranslateUrl($store)
97 | {
98 | return $this->getUrl(
99 | 'aromicon_deepl/review/translate',
100 | ['store' => $store->getId(), 'review_id' => $this->getRequest()->getParam('id')]
101 | );
102 | }
103 |
104 | /**
105 | * Check whether it is single store mode
106 | *
107 | * @return bool
108 | */
109 | public function isSingleStoreMode()
110 | {
111 | return $this->_storeManager->isSingleStoreMode();
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Cms/Page/Edit/TranslateButton.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Block\Adminhtml\Cms\Page\Edit;
11 |
12 | class TranslateButton extends \Magento\Backend\Block\Widget\Container
13 | {
14 | /**
15 | * @var \Magento\Store\Api\StoreManagementInterface
16 | */
17 | protected $storeManagement;
18 |
19 | /**
20 | * @var \Magento\Framework\Registry
21 | */
22 | protected $coreRegistry;
23 |
24 | /**
25 | * @var \Aromicon\Deepl\Helper\Config
26 | */
27 | protected $config;
28 |
29 | /**
30 | * @param \Magento\Backend\Block\Widget\Context $context
31 | * @param \Magento\Store\Api\StoreManagementInterface $storeManagement
32 | * @param array $data
33 | */
34 | public function __construct(
35 | \Magento\Backend\Block\Widget\Context $context,
36 | \Magento\Framework\Registry $coreRegistry,
37 | \Magento\Store\Model\StoreManagerInterface $storeManagement,
38 | \Aromicon\Deepl\Helper\Config $config,
39 | array $data = []
40 | ) {
41 | $this->storeManagement = $storeManagement;
42 | $this->coreRegistry = $coreRegistry;
43 | $this->config = $config;
44 | parent::__construct($context, $data);
45 | }
46 |
47 | /**
48 | * Prepare button and grid
49 | *
50 | * @return \Magento\Catalog\Block\Adminhtml\Product
51 | */
52 | protected function _prepareLayout()
53 | {
54 | $addButtonProps = [
55 | 'id' => 'translate_cms_page',
56 | 'label' => __('Translate'),
57 | 'class' => 'add options-scrollable',
58 | 'button_class' => 'options-scrollable',
59 | 'class_name' => \Magento\Backend\Block\Widget\Button\SplitButton::class,
60 | 'options' => $this->_getTranslateOptions(),
61 | ];
62 |
63 | if ($this->config->hasApiKey()) {
64 | $this->buttonList->add('translate', $addButtonProps);
65 | }
66 |
67 | return parent::_prepareLayout();
68 | }
69 |
70 | /**
71 | * Retrieve options for 'Add Product' split button
72 | *
73 | * @return array
74 | */
75 | protected function _getTranslateOptions()
76 | {
77 | $splitButtonOptions = [];
78 | $stores = $this->storeManagement->getStores();
79 |
80 | foreach ($stores as $key => $store) {
81 | $splitButtonOptions[$key] = [
82 | 'label' => __($store->getName().' '.$this->config->getStoreLanguage($store)),
83 | 'onclick' => "setLocation('" . $this->_getTranslateUrl($store) . "')"
84 | ];
85 | }
86 |
87 | return $splitButtonOptions;
88 | }
89 |
90 | /**
91 | * Retrieve product create url by specified product type
92 | *
93 | * @param string $type
94 | * @return string
95 | */
96 | protected function _getTranslateUrl($store)
97 | {
98 | return $this->getUrl(
99 | 'aromicon_deepl/cms_page/translate',
100 | ['store' => $store->getId(), 'page_id' => $this->getCurrentPage()->getId()]
101 | );
102 | }
103 |
104 | /**
105 | * @return \Magento\Cms\Api\Data\PageInterface
106 | */
107 | public function getCurrentPage()
108 | {
109 | return $this->coreRegistry->registry('cms_page');
110 | }
111 |
112 | /**
113 | * Check whether it is single store mode
114 | *
115 | * @return bool
116 | */
117 | public function isSingleStoreMode()
118 | {
119 | return $this->_storeManager->isSingleStoreMode();
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Cms/Block/Edit/TranslateButton.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Block\Adminhtml\Cms\Block\Edit;
11 |
12 | class TranslateButton extends \Magento\Backend\Block\Widget\Container
13 | {
14 | /**
15 | * @var \Magento\Store\Api\StoreManagementInterface
16 | */
17 | protected $storeManagement;
18 |
19 | /**
20 | * @var \Magento\Framework\Registry
21 | */
22 | protected $coreRegistry;
23 |
24 | /**
25 | * @var \Aromicon\Deepl\Helper\Config
26 | */
27 | protected $config;
28 |
29 | /**
30 | * @param \Magento\Backend\Block\Widget\Context $context
31 | * @param \Magento\Store\Api\StoreManagementInterface $storeManagement
32 | * @param array $data
33 | */
34 | public function __construct(
35 | \Magento\Backend\Block\Widget\Context $context,
36 | \Magento\Framework\Registry $coreRegistry,
37 | \Magento\Store\Model\StoreManagerInterface $storeManagement,
38 | \Aromicon\Deepl\Helper\Config $config,
39 | array $data = []
40 | ) {
41 | $this->storeManagement = $storeManagement;
42 | $this->coreRegistry = $coreRegistry;
43 | $this->config = $config;
44 | parent::__construct($context, $data);
45 | }
46 |
47 | /**
48 | * Prepare button and grid
49 | *
50 | * @return \Magento\Catalog\Block\Adminhtml\Product
51 | */
52 | protected function _prepareLayout()
53 | {
54 | $addButtonProps = [
55 | 'id' => 'translate_cms_block',
56 | 'label' => __('Translate'),
57 | 'class' => 'add options-scrollable',
58 | 'button_class' => 'options-scrollable',
59 | 'class_name' => \Magento\Backend\Block\Widget\Button\SplitButton::class,
60 | 'options' => $this->_getTranslateOptions(),
61 | ];
62 | if ($this->config->hasApiKey()) {
63 | $this->buttonList->add('translate', $addButtonProps);
64 | }
65 |
66 | return parent::_prepareLayout();
67 | }
68 |
69 | /**
70 | * Retrieve options for 'Add Product' split button
71 | *
72 | * @return array
73 | */
74 | protected function _getTranslateOptions()
75 | {
76 | $splitButtonOptions = [];
77 | $stores = $this->storeManagement->getStores();
78 |
79 | foreach ($stores as $key => $store) {
80 | $splitButtonOptions[$key] = [
81 | 'label' => __($store->getName().' '.$this->config->getStoreLanguage($store)),
82 | 'onclick' => "setLocation('" . $this->_getTranslateUrl($store) . "')"
83 | ];
84 | }
85 |
86 | return $splitButtonOptions;
87 | }
88 |
89 | /**
90 | * Retrieve product create url by specified product type
91 | *
92 | * @param string $type
93 | * @return string
94 | */
95 | protected function _getTranslateUrl($store)
96 | {
97 | return $this->getUrl(
98 | 'aromicon_deepl/cms_block/translate',
99 | ['store' => $store->getId(), 'block_id' => $this->getCurrentBlock()->getId()]
100 | );
101 | }
102 |
103 | /**
104 | * @return \Magento\Cms\Api\Data\BlockInterface
105 | */
106 | public function getCurrentBlock()
107 | {
108 | return $this->coreRegistry->registry('cms_block');
109 | }
110 |
111 | /**
112 | * Check whether it is single store mode
113 | *
114 | * @return bool
115 | */
116 | public function isSingleStoreMode()
117 | {
118 | return $this->_storeManager->isSingleStoreMode();
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Catalog/Attribute/Edit/TranslateButton.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Block\Adminhtml\Catalog\Attribute\Edit;
11 |
12 | class TranslateButton extends \Magento\Backend\Block\Widget\Container
13 | {
14 | /**
15 | * @var \Magento\Store\Api\StoreManagementInterface
16 | */
17 | protected $storeManagement;
18 |
19 | /**
20 | * @var \Magento\Framework\Registry
21 | */
22 | protected $coreRegistry;
23 |
24 | /**
25 | * @var \Aromicon\Deepl\Helper\Config
26 | */
27 | protected $config;
28 |
29 | /**
30 | * @param \Magento\Backend\Block\Widget\Context $context
31 | * @param \Magento\Store\Api\StoreManagementInterface $storeManagement
32 | * @param array $data
33 | */
34 | public function __construct(
35 | \Magento\Backend\Block\Widget\Context $context,
36 | \Magento\Framework\Registry $coreRegistry,
37 | \Magento\Store\Model\StoreManagerInterface $storeManagement,
38 | \Aromicon\Deepl\Helper\Config $config,
39 | array $data = []
40 | ) {
41 | $this->storeManagement = $storeManagement;
42 | $this->coreRegistry = $coreRegistry;
43 | $this->config = $config;
44 | parent::__construct($context, $data);
45 | }
46 |
47 | /**
48 | * Prepare button and grid
49 | *
50 | * @return \Magento\Catalog\Block\Adminhtml\Product
51 | */
52 | protected function _prepareLayout()
53 | {
54 | $addButtonProps = [
55 | 'id' => 'translate_cms_block',
56 | 'label' => __('Translate'),
57 | 'class' => 'add options-scrollable',
58 | 'button_class' => 'options-scrollable',
59 | 'class_name' => \Magento\Backend\Block\Widget\Button\SplitButton::class,
60 | 'options' => $this->_getTranslateOptions(),
61 | ];
62 |
63 | if ($this->config->hasApiKey()) {
64 | $this->buttonList->add('add_new', $addButtonProps);
65 | }
66 |
67 | return parent::_prepareLayout();
68 | }
69 |
70 | /**
71 | * Retrieve options for 'Add Product' split button
72 | *
73 | * @return array
74 | */
75 | protected function _getTranslateOptions()
76 | {
77 | $splitButtonOptions = [];
78 | $stores = $this->storeManagement->getStores();
79 |
80 | foreach ($stores as $key => $store) {
81 | $splitButtonOptions[$key] = [
82 | 'label' => __($store->getName().' '.$this->config->getStoreLanguage($store)),
83 | 'onclick' => "setLocation('" . $this->_getTranslateUrl($store) . "')"
84 | ];
85 | }
86 |
87 | return $splitButtonOptions;
88 | }
89 |
90 | /**
91 | * Retrieve product create url by specified product type
92 | *
93 | * @param string $type
94 | * @return string
95 | */
96 | protected function _getTranslateUrl($store)
97 | {
98 | return $this->getUrl(
99 | 'aromicon_deepl/catalog_attribute/translate',
100 | ['store' => $store->getId(), 'attribute_id' => $this->getCurrentAttribute()->getId()]
101 | );
102 | }
103 |
104 | /**
105 | * @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute
106 | */
107 | public function getCurrentAttribute()
108 | {
109 | return $this->coreRegistry->registry('entity_attribute');
110 | }
111 |
112 | /**
113 | * Check whether it is single store mode
114 | *
115 | * @return bool
116 | */
117 | public function isSingleStoreMode()
118 | {
119 | return $this->_storeManager->isSingleStoreMode();
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/Model/Translator/Cms/Block.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\Translator\Cms;
10 |
11 | use Magento\Framework\Exception\LocalizedException;
12 |
13 | class Block
14 | {
15 | /**
16 | * @var \Magento\Cms\Api\BlockRepositoryInterface
17 | */
18 | private $blockRepository;
19 |
20 | /**
21 | * @var \Magento\Cms\Api\Data\BlockInterfaceFactory
22 | */
23 | private $blockInterfaceFactory;
24 |
25 | /**
26 | * @var \Aromicon\Deepl\Api\TranslatorInterface
27 | */
28 | private $translator;
29 |
30 | /**
31 | * @var \Aromicon\Deepl\Helper\Config
32 | */
33 | private $config;
34 |
35 | /**
36 | * @var \Magento\Store\Model\StoreManagerInterface
37 | */
38 | private $storeManager;
39 | /**
40 | * Block constructor.
41 | * @param \Magento\Cms\Api\BlockRepositoryInterface $blockRepository
42 | * @param \Magento\Cms\Api\Data\BlockInterfaceFactory $blockInterfaceFactory
43 | * @param \Aromicon\Deepl\Api\TranslatorInterface $translator
44 | * @param \Aromicon\Deepl\Helper\Config $config
45 | * @param \Magento\Store\Model\StoreManagerInterface $storeManager
46 | */
47 | public function __construct(
48 | \Magento\Cms\Api\BlockRepositoryInterface $blockRepository,
49 | \Magento\Cms\Api\Data\BlockInterfaceFactory $blockInterfaceFactory,
50 | \Aromicon\Deepl\Api\TranslatorInterface $translator,
51 | \Aromicon\Deepl\Helper\Config $config,
52 | \Magento\Store\Model\StoreManagerInterface $storeManagement
53 | ) {
54 | $this->blockRepository = $blockRepository;
55 | $this->blockInterfaceFactory = $blockInterfaceFactory;
56 | $this->translator = $translator;
57 | $this->config = $config;
58 | $this->storeManager = $storeManagement;
59 | }
60 |
61 | /**
62 | * @param $blockId int
63 | * @param $fromStoreId int
64 | * @param $toStoreId int
65 | * @throws \Magento\Framework\Exception\LocalizedException
66 | */
67 | public function translateAndCopy($blockId, $toStoreId)
68 | {
69 | /** @var \Magento\Cms\Model\Block $block */
70 | $block = $this->blockRepository->getById($blockId);
71 |
72 | $sourceLanguage = $this->config->getSourceLanguage($toStoreId);
73 | $targetLanguage = $this->config->getLanguageCodeByStoreId($toStoreId, true);
74 | /** @var \Magento\Cms\Api\Data\BlockInterface $translatedBlock */
75 | $translatedBlock = $this->blockInterfaceFactory->create();
76 |
77 | $blockFields = $this->config->getTranslatableBlockFields();
78 |
79 | if (in_array('title', $blockFields)) {
80 | $translatedTitle = $this->translator->translate($block->getTitle(), $sourceLanguage, $targetLanguage);
81 | } else {
82 | $translatedTitle = $block->getTitle();
83 | }
84 |
85 | if (in_array('content', $blockFields)) {
86 | $translatedContent = $this->translator->translate($block->getContent(), $sourceLanguage, $targetLanguage);
87 | } else {
88 | $translatedContent = $block->getContent();
89 | }
90 |
91 | $translatedBlock
92 | ->setTitle($translatedTitle)
93 | ->setContent($translatedContent)
94 | ->setIsActive($block->isActive())
95 | ->setIdentifier($block->getIdentifier())
96 | ->setStoreId($toStoreId);
97 |
98 | $this->removeStoreFromBlock($block, $toStoreId);
99 |
100 | $this->blockRepository->save($block);
101 | $this->blockRepository->save($translatedBlock);
102 | }
103 |
104 | /**
105 | * @param \Magento\Cms\Model\Block $block
106 | * @param $storeId
107 | */
108 | protected function removeStoreFromBlock($block, $storeId)
109 | {
110 | if (isset($block->getStoreId()[0]) && $block->getStoreId()[0] == 0) {
111 | $allStores = $this->storeManager->getStores();
112 |
113 | foreach ($allStores as $store) {
114 | $allStoreIds[] = $store->getId();
115 | }
116 | } else {
117 | $allStoreIds = $block->getStoreId();
118 | }
119 |
120 | $block->setStoreId(array_diff($allStoreIds, [$storeId]));
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/Model/Translator/Cms/Page.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\Translator\Cms;
10 |
11 | use Magento\Cms\Api\Data\PageInterface;
12 | use Magento\Framework\Exception\LocalizedException;
13 |
14 | class Page
15 | {
16 | /**
17 | * @var \Magento\Cms\Api\PageRepositoryInterface
18 | */
19 | private $pageRepository;
20 |
21 | /**
22 | * @var \Magento\Cms\Api\Data\PageInterfaceFactory
23 | */
24 | private $pageInterfaceFactory;
25 |
26 | /**
27 | * @var \Aromicon\Deepl\Api\TranslatorInterface
28 | */
29 | private $translator;
30 |
31 | /**
32 | * @var \Aromicon\Deepl\Helper\Config
33 | */
34 | private $config;
35 |
36 | /**
37 | * @var \Magento\Store\Model\StoreManagerInterface
38 | */
39 | private $storeManagement;
40 |
41 | /**
42 | * @var \Magento\Framework\Filter\FilterManager
43 | */
44 | private $filterManager;
45 |
46 | /**
47 | * Page constructor.
48 | * @param \Magento\Cms\Api\PageRepositoryInterface $pageRepository
49 | * @param \Magento\Cms\Api\Data\PageInterfaceFactory $pageInterfaceFactory
50 | * @param \Aromicon\Deepl\Api\TranslatorInterface $translator
51 | * @param \Aromicon\Deepl\Helper\Config $config
52 | * @param \Magento\Store\Model\StoreManagerInterface $storeManagement
53 | * @param \Magento\Framework\Filter\FilterManager $filterManager
54 | */
55 | public function __construct(
56 | \Magento\Cms\Api\PageRepositoryInterface $pageRepository,
57 | \Magento\Cms\Api\Data\PageInterfaceFactory $pageInterfaceFactory,
58 | \Aromicon\Deepl\Api\TranslatorInterface $translator,
59 | \Aromicon\Deepl\Helper\Config $config,
60 | \Magento\Store\Model\StoreManagerInterface $storeManagement,
61 | \Magento\Framework\Filter\FilterManager $filterManager
62 | ) {
63 | $this->pageRepository = $pageRepository;
64 | $this->pageInterfaceFactory = $pageInterfaceFactory;
65 | $this->translator = $translator;
66 | $this->config = $config;
67 | $this->storeManagement = $storeManagement;
68 | $this->filterManager = $filterManager;
69 | }
70 |
71 | /**
72 | * @param $pageId int
73 | * @param $fromStoreId int
74 | * @param $toStoreId int
75 | * @throws \Magento\Framework\Exception\LocalizedException
76 | */
77 | public function translateAndCopy($pageId, $toStoreId)
78 | {
79 | $page = $this->pageRepository->getById($pageId);
80 |
81 | $sourceLanguage = $this->config->getSourceLanguage($toStoreId);
82 | $targetLanguage = $this->config->getLanguageCodeByStoreId($toStoreId, true);
83 | /** @var \Magento\Cms\Api\Data\PageInterface $translatedPage */
84 | $translatedPage = $this->pageInterfaceFactory->create();
85 |
86 | $translatedPage->setData($page->getData())
87 | ->setPageId(null)
88 | ->setCreatedAt(null)
89 | ->setUpdatedAt(null)
90 | ->setStoreId($toStoreId);
91 |
92 | $pageFields = $this->config->getTranslatablePageFields();
93 |
94 | foreach ($pageFields as $field) {
95 | if ($page->getData($field) == '') {
96 | continue;
97 | }
98 |
99 | $translatedText = $this->translator->translate($page->getData($field), $sourceLanguage, $targetLanguage);
100 |
101 | if ($field == 'identifier') {
102 | $translatedText = $this->filterManager->translitUrl($translatedText);
103 | }
104 |
105 | $translatedPage->setData($field, $translatedText);
106 | }
107 |
108 | $this->removeStoreFromPage($page, $toStoreId);
109 |
110 | $this->pageRepository->save($page);
111 | $this->pageRepository->save($translatedPage);
112 | }
113 |
114 | /**
115 | * @param PageInterface $page
116 | * @param $storeId
117 | * @return array
118 | */
119 | protected function removeStoreFromPage($page, $storeId)
120 | {
121 | if (isset($page->getStoreId()[0]) && $page->getStoreId()[0] == 0) {
122 | $allStores = $this->storeManagement->getStores();
123 | foreach ($allStores as $store) {
124 | $allStoreIds[] = $store->getId();
125 | }
126 | } else {
127 | $allStoreIds = $page->getStoreId();
128 | }
129 |
130 | return $page->setStoreId(array_diff($allStoreIds, [$storeId]));
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/Model/Translator/Catalog/Attribute.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\Translator\Catalog;
10 |
11 | use Magento\Eav\Api\Data\AttributeOptionInterface;
12 |
13 | class Attribute
14 | {
15 | /**
16 | * @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface
17 | */
18 | private $attributeRepository;
19 |
20 | /**
21 | * @var \Aromicon\Deepl\Api\TranslatorInterface
22 | */
23 | private $translator;
24 |
25 | /**
26 | * @var \Aromicon\Deepl\Helper\Config
27 | */
28 | private $config;
29 |
30 | /**
31 | * @var \Magento\Catalog\Model\ResourceModel\Product
32 | */
33 | private $productResource;
34 |
35 | /**
36 | * @var \Magento\Catalog\Model\ResourceModel\Attribute
37 | */
38 | private $attributeResource;
39 |
40 | public function __construct(
41 | \Magento\Eav\Api\AttributeRepositoryInterface $attributeRepository,
42 | \Aromicon\Deepl\Api\TranslatorInterface $translator,
43 | \Aromicon\Deepl\Helper\Config $config,
44 | \Magento\Catalog\Model\ResourceModel\Attribute $attributeResource
45 | ) {
46 | $this->attributeRepository = $attributeRepository;
47 | $this->translator = $translator;
48 | $this->config = $config;
49 | $this->attributeResource = $attributeResource;
50 | }
51 |
52 | /**
53 | * @param $attributeId int
54 | * @param $fromStoreId int
55 | * @param $toStoreId int
56 | * @throws \Magento\Framework\Exception\LocalizedException
57 | * @throws \Exception
58 | */
59 | public function translateAndCopy($attributeId, $toStoreId)
60 | {
61 | /** @var \Magento\Eav\Model\Entity\Attribute $attribute */
62 | $attribute = $this->attributeRepository->get(\Magento\Catalog\Model\Product::ENTITY, $attributeId);
63 |
64 | $sourceStoreId = $this->config->getSourceStoreId($toStoreId);
65 | $sourceLanguage = $this->config->getSourceLanguage($toStoreId);
66 | $targetLanguage = $this->config->getLanguageCodeByStoreId($toStoreId, true);
67 |
68 | $labels = $attribute->getStoreLabels();
69 | $srcLabel = array_key_exists($sourceStoreId, $labels)
70 | ? $labels[$sourceStoreId]
71 | : $attribute->getDefaultFrontendLabel();
72 | $labels[$toStoreId] = $this->translator->translate($srcLabel, $sourceLanguage, $targetLanguage);
73 |
74 | $attribute->setStoreLabels($labels);
75 | $this->attributeRepository->save($attribute);
76 |
77 | $attribute->setStoreId($sourceStoreId);
78 |
79 | if (in_array($attribute->getFrontendInput(), ['select', 'multiselect'])
80 | && in_array(get_class($attribute->getSource()), [\Magento\Eav\Model\Entity\Attribute\Source\Table::class, null])) {
81 | $options = $attribute->getOptions();
82 |
83 | if (!empty($options)) {
84 | foreach ($options as $option) {
85 | if ($option->getValue() == '') {
86 | continue;
87 | }
88 |
89 | $srcOptionLabel = $option->getLabel();
90 | $translatedOptionLabel = $this->translator
91 | ->translate($srcOptionLabel, $sourceLanguage, $targetLanguage);
92 |
93 | $this->saveAttributeOption($option, $translatedOptionLabel, $toStoreId);
94 | }
95 | }
96 | }
97 | }
98 |
99 | /**
100 | * @param AttributeOptionInterface $option
101 | * @param string $value
102 | * @param int|string $storeId
103 | */
104 | protected function saveAttributeOption($option, $value, $storeId)
105 | {
106 | $optionId = $option->getValue();
107 | $connection = $this->attributeResource->getConnection();
108 | $table = $this->attributeResource->getTable('eav_attribute_option_value');
109 |
110 | $select = $connection->select()
111 | ->from($table)
112 | ->where('option_id = ?', $optionId)
113 | ->where('store_id = ?', $storeId);
114 |
115 | $result = $connection->fetchOne($select);
116 |
117 | if ($result) {
118 | $connection->update($table, ['value' => $value], ['option_id = ?' => $optionId, 'store_id = ?' => $storeId]);
119 | } else {
120 | $optionValue = [
121 | 'option_id' => $optionId,
122 | 'store_id' => $storeId,
123 | 'value' => $value
124 | ];
125 |
126 | $connection->insert($table, $optionValue);
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/Model/Translator/Review.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 | namespace Aromicon\Deepl\Model\Translator;
10 |
11 | use Magento\Framework\Exception\LocalizedException;
12 |
13 | class Review
14 | {
15 | /**
16 | * @var \Magento\Review\Model\ResourceModel\Review\CollectionFactory
17 | */
18 | protected $reviewCollectionFactory;
19 |
20 | /**
21 | * @var \Magento\Review\Model\ResourceModel\Rating\CollectionFactory
22 | */
23 | protected $ratingCollectionFactory;
24 |
25 | /**
26 | * @var \Magento\Review\Model\ReviewFactory
27 | */
28 | protected $reviewFactory;
29 |
30 | /**
31 | * @var \Aromicon\Deepl\Api\TranslatorInterface
32 | */
33 | protected $translator;
34 |
35 | /**
36 | * @var \Aromicon\Deepl\Helper\Config
37 | */
38 | protected $config;
39 |
40 | /**
41 | * Review constructor.
42 | * @param \Magento\Review\Model\ResourceModel\Review\CollectionFactory $reviewCollectionFactory
43 | * @param \Magento\Review\Model\ReviewFactory $reviewFactory
44 | * @param \Aromicon\Deepl\Api\TranslatorInterface $translator
45 | * @param \Aromicon\Deepl\Helper\Config $config
46 | */
47 | public function __construct(
48 | \Magento\Review\Model\ResourceModel\Review\CollectionFactory $reviewCollectionFactory,
49 | \Magento\Review\Model\ReviewFactory $reviewFactory,
50 | \Magento\Review\Model\ResourceModel\Rating\Option\Vote\CollectionFactory $ratingCollectionFactory,
51 | \Aromicon\Deepl\Api\TranslatorInterface $translator,
52 | \Aromicon\Deepl\Helper\Config $config
53 | ) {
54 | $this->ratingCollectionFactory = $ratingCollectionFactory;
55 | $this->reviewCollectionFactory = $reviewCollectionFactory;
56 | $this->reviewFactory = $reviewFactory;
57 | $this->translator = $translator;
58 | $this->config = $config;
59 | }
60 |
61 | /**
62 | * @param $reviewId int
63 | * @param $fromStoreId int
64 | * @param $toStoreId int
65 | * @throws \Magento\Framework\Exception\LocalizedException
66 | */
67 | public function translateAndCopy($reviewId, $toStoreId)
68 | {
69 | /** @var \Magento\Review\Model\Review $review */
70 | $review = $this->reviewFactory->create()->load($reviewId);
71 |
72 | if ($this->checkForDuplicate($review, $toStoreId)) {
73 | throw new LocalizedException(__('Duplicate found for Review ID %1', $reviewId));
74 | }
75 |
76 | $sourceLanguage = $this->config->getSourceLanguage($toStoreId);
77 | $targetLanguage = $this->config->getLanguageCodeByStoreId($toStoreId, true);
78 |
79 | $translatedTitle = $this->translator->translate($review->getTitle(), $sourceLanguage, $targetLanguage);
80 | $translatedDetail = $this->translator->translate($review->getDetail(), $sourceLanguage, $targetLanguage);
81 |
82 | $translatedReview = clone $review;
83 |
84 | $translatedReview->setId(null)
85 | ->setDetailId(null)
86 | ->setStores([$toStoreId])
87 | ->setStoreId($toStoreId)
88 | ->setTitle($translatedTitle)
89 | ->setDetail($translatedDetail);
90 |
91 | $translatedReview->save();
92 | //Bug Fixing Wrong Date at Model Save
93 | $translatedReview->setCreatedAt($review->getCreatedAt())->save();
94 |
95 | $this->copyRatings($review, $translatedReview);
96 | }
97 |
98 | /**
99 | * @param \Magento\Review\Model\Review $review
100 | * @param int $toStoreId
101 | * @return bool
102 | */
103 | public function checkForDuplicate($review, $toStoreId)
104 | {
105 | /** @var \Magento\Review\Model\ResourceModel\Review\Collection $collection */
106 | $collection = $this->reviewCollectionFactory->create();
107 | $collection->addEntityFilter($review->getEntityId(), $review->getEntityPkValue())
108 | ->addStoreFilter($toStoreId)
109 | ->addStoreData()
110 | ->addFieldToFilter('nickname', $review->getNickname());
111 |
112 | return !empty($collection->getAllIds());
113 | }
114 |
115 | /**
116 | * @param \Magento\Review\Model\Review $review
117 | * @param \Magento\Review\Model\Review $translatedReview
118 | */
119 | public function copyRatings($review, $translatedReview)
120 | {
121 | /** @var \Magento\Review\Model\ResourceModel\Rating\Option\Vote\Collection $collection */
122 | $collection = $this->ratingCollectionFactory->create();
123 | $collection->setReviewFilter($review->getId());
124 |
125 | foreach ($collection->getItems() as $vote) {
126 | $copyVote = clone $vote;
127 | $copyVote->setVoteId(null)
128 | ->setReviewId($translatedReview->getId())
129 | ->save();
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # Magento 2 Aromicon DeepL Translate
2 |
3 | This Magento 2 module extends your shop with the possibility to automatically translate CMS pages, CMS blocks, products,
4 | attributes, ratings and categories with the help of DeepL API.
5 |
6 |
7 |
8 |
9 |
10 | A DeepL API Key is required and can be created [here](https://www.deepl.com/pro?cta=header-prices#developer/)
11 |
12 | ### FREE DEEPL API KEY + 500.000 Words monthly
13 | You can register for new Deepl Free API [here](https://www.deepl.com/pro?cta=header-prices#developer/)
14 |
15 | Currently Supported Languages:
16 |
17 | * BG - Bulgarian
18 | * CS - Czech
19 | * DA - Danish
20 | * DE - German
21 | * EL - Greek
22 | * EN - English
23 | * ES - Spanish
24 | * ET - Estonian
25 | * FI - Finnish
26 | * FR - French
27 | * HU - Hungarian
28 | * ID - Indonesian
29 | * IT - Italian
30 | * JA - Japanese
31 | * KO - Korean
32 | * LT - Lithuanian
33 | * LV - Latvian
34 | * NB - Norwegian (Bokmål)
35 | * NL - Dutch
36 | * PL - Polish
37 | * PT - Portuguese (all Portuguese varieties mixed)
38 | * RO - Romanian
39 | * RU - Russian
40 | * SK - Slovak
41 | * SL - Slovenian
42 | * SV - Swedish
43 | * TR - Turkish
44 | * UK - Ukrainian
45 | * ZH - Chinese
46 |
47 | ## Installation
48 | ### Requirements
49 | Magento CE > 2.2.5
50 |
51 | ### Composer
52 | Go to Magento 2 Root Folder and execute following commands as web user (mostly www-data).
53 | ```
54 | composer config repositories.aromicon_deepl vcs git@github.com:aromicon/magento2-deepl.git
55 | composer require aromicon/module-deepl
56 | bin/magento module:enable Aromicon_Deepl
57 | bin/magento setup:upgrade
58 | bin/magento setup:di:compile
59 | bin/magento cache:enable (only needed, if caches were enabled before)
60 | ```
61 |
62 | ### Manual (not recommended)
63 | Go to your Magento 2 root directory and create a folder app/code/Aromicon/Deepl. Extract Archive to this folder and
64 | execute following commands as web user (mostly www-data).
65 |
66 | ```
67 | bin/magento module:enable Aromicon_Deepl
68 | bin/magento setup:upgrade
69 | bin/magento setup:di:compile
70 | bin/magento cache:enable (only needed, if caches were enabled before)
71 | ```
72 |
73 | ## Magento 2 Configuration
74 |
75 | Aromicon Deepl Translation Configuration can be found under ```Stores > Configuration > Aromicon > Deepl Translate```
76 |
77 | First, you need to Specifiy your Default Storeview, this is your storeview where you normally add your content ind your default language.
78 |
79 | Second, you need to chosse between API Version wih depends on Your Account. You can choose "Free" or "Pro"
80 |
81 | Third, you need to enter your API Key provided by [DeepL Pro](https://www.deepl.com/pro.html).
82 |
83 | You can also configure, which fields should be translated by default for CMS Pages, Products and Categories.
84 |
85 | ## Usage
86 |
87 | All translation will be added per storeview. The target language will be recieved from your storeview locale settings.
88 |
89 | ### Translate Magento 2 CMS Blocks
90 |
91 | Goto ```Content > CMS > Blocks``` and open the block, you want to translate. At the edit form on top right corner,
92 | there will be a new Translate Button. Select the Storeview, where the Block should be translated and copied.
93 | By Default the block will be copied to selected storeview and the Title and Content will be translated.
94 |
95 | ### Translate CMS Pages
96 |
97 | Goto ```Content > CMS > Pages``` and open the page, you want to translate. At the edit form on top right corner,
98 | there will be a new Translate Button. Select the Storeview, where the Block should be translated and copied.
99 | By Default the page will be copied to selected storeview and the Title, Url Key, Meta Information and Content will be translated.
100 |
101 | ### Translate Attributes
102 |
103 | All Magento 2 Attributes can be translated, but only the Store Labels will be translated. If the attribute is a dropdown or multiselect
104 | attribute, without a custom source model, the option walues will be translated as well.
105 |
106 | Goto ````Stores > Attributes > Product```` and select the needed attribute. Use the translate button on top right corner.
107 |
108 |
109 | ### Translate Magento 2 Categories
110 |
111 | Name, Page Title, Content, Url Key and Meta Information will be translated on Categories. If you open a Category you will see the Translate button on top right corner.
112 | Translated Content will be copied to the selected storeview.
113 |
114 | ### Translate Products
115 |
116 | By Default Name, Short Description, Description, Url Key and Meta Information will be translated. You can also configure
117 | all attributes of type text or textarea to be translated as well. Just go to your Product Edit View and hit the Translate
118 | Button for your desired storeview. Translated data will be copied to selected storeview.
119 |
120 | ### Translate Products Reviews
121 |
122 | Product Reviews can be translated too. Just go to ```Marketing > User Content > Reviews``` and open a review,
123 | then select a storeview from the Translate Button.
124 |
125 | ## Aromicon Deepl Pro
126 | You are looking for Batch Translation from Backend or Console? Try our [Aromicon Translate Pro Magento 2 Module](https://www.aromicon.de/magento-download-extensions-modules/de/magento-2-translate-pro.html)
127 |
128 |
129 | ## Support
130 |
131 | Pull request, issues and features are always welcome.
132 |
133 |
134 | We ❤ Magento. by [aromicon](https://www.aromicon.de)
135 | Made by [aromicon](https://www.aromicon.de)
136 |
137 |
--------------------------------------------------------------------------------
/etc/adminhtml/system.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 | Aromicon
15 |
16 |
17 | Deepl Translate
18 | aromicon
19 | Aromicon_Deepl::config
20 |
21 | Aromicon\Deepl\Block\Adminhtml\System\Config\Fieldset\Info
22 |
23 |
24 |
25 | Deepl General
26 |
27 | Default Store
28 | Magento\Store\Model\System\Store
29 |
30 |
31 |
32 | Deepl API
33 |
34 | API Version
35 | Aromicon\Deepl\Model\System\Config\Version
36 |
37 |
38 | API Key
39 |
40 |
41 | API Timeout
42 | API Call Timeout in sec. Default 30 sec.
43 |
44 |
45 | Tag Handling
46 | Aromicon\Deepl\Model\System\Config\TagHandling
47 |
48 |
49 | Split Sentences
50 | Aromicon\Deepl\Model\System\Config\SplitSentence
51 |
52 |
53 | Formality
54 | Aromicon\Deepl\Model\System\Config\Formality
55 |
56 |
57 |
58 | CMS Translate
59 |
60 | CMS Block Translatable Fields
61 | Aromicon\Deepl\Model\System\Config\BlockFields
62 |
63 |
64 | CMS Page Translatable Fields
65 | Aromicon\Deepl\Model\System\Config\PageFields
66 |
67 |
68 |
69 | Product Translate
70 |
71 | Product Translatable Fields
72 | Aromicon\Deepl\Model\System\Config\ProductFields
73 |
74 |
75 |
76 | Category Translate
77 |
78 | Category Translatable Fields
79 | Aromicon\Deepl\Model\System\Config\CategoryFields
80 |
81 |
82 |
83 | Log
84 |
85 | Enable Request / Response Log
86 | Magento\Config\Model\Config\Source\Yesno
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/Model/Client/Deepl.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2018 aromicon GmbH (http://www.aromicon.de)
7 | * @license Commercial https://www.aromicon.de/magento-download-extensions-modules/de/license
8 | */
9 |
10 | namespace Aromicon\Deepl\Model\Client;
11 |
12 | use Aromicon\Deepl\Api\TranslatorInterface;
13 | use Aromicon\Deepl\Helper\Config;
14 | use Laminas\Http\Client;
15 | use Laminas\Http\Request;
16 | use Laminas\Http\Response;
17 | use Magento\Framework\App\ObjectManager;
18 | use Magento\Framework\Exception\LocalizedException;
19 | use Magento\Framework\Filter\DirectiveProcessor\DependDirective;
20 | use Magento\Framework\Filter\DirectiveProcessor\IfDirective;
21 | use Magento\Framework\Filter\DirectiveProcessor\LegacyDirective;
22 | use Magento\Framework\Filter\DirectiveProcessor\TemplateDirective;
23 | use Magento\Framework\Filter\DirectiveProcessorInterface;
24 |
25 | class Deepl implements TranslatorInterface
26 | {
27 | const AVAILABLE_LANGUAGES = [
28 | 'AR',
29 | 'BG',
30 | 'CS',
31 | 'DA',
32 | 'DE',
33 | 'EL',
34 | 'EN-GB',
35 | 'EN-US',
36 | 'EN',
37 | 'ES',
38 | 'ET',
39 | 'FI',
40 | 'FR',
41 | 'HU',
42 | 'ID',
43 | 'IT',
44 | 'JA',
45 | 'KO',
46 | 'LT',
47 | 'LV',
48 | 'NB',
49 | 'NL',
50 | 'PL',
51 | 'PT-PT',
52 | 'PT-BR',
53 | 'PT',
54 | 'RO',
55 | 'RU',
56 | 'SK',
57 | 'SL',
58 | 'SV',
59 | 'TR',
60 | 'UK',
61 | 'ZH',
62 | 'ZH-HANS',
63 | 'ZH-HANT'
64 | ];
65 |
66 |
67 | private Config $config;
68 | private Client $client;
69 | private array $usage = [];
70 |
71 | /**
72 | * @var \Psr\Log\LoggerInterface
73 | */
74 | private $logger;
75 | private array $directives = [];
76 | protected array $directiveProcessors;
77 |
78 | public function __construct(
79 | Config $config,
80 | Client $client,
81 | \Psr\Log\LoggerInterface $logger,
82 | array $directiveProcessors = [],
83 | ) {
84 | $this->config = $config;
85 | $this->client = $client;
86 | $this->logger = $logger;
87 |
88 | if (empty($directiveProcessors)) {
89 | $directiveProcessors = [
90 | 'depend' => ObjectManager::getInstance()->get(DependDirective::class),
91 | 'if' => ObjectManager::getInstance()->get(IfDirective::class),
92 | 'template' => ObjectManager::getInstance()->get(TemplateDirective::class),
93 | 'legacy' => ObjectManager::getInstance()->get(LegacyDirective::class),
94 | ];
95 | }
96 |
97 | $this->directiveProcessors = $directiveProcessors;
98 | }
99 |
100 | /**
101 | * Check if API ist Working
102 | * @return bool
103 | * @throws LocalizedException
104 | */
105 | public function isValid()
106 | {
107 | return $this->getCharacterCount() !== false;
108 | }
109 |
110 | /**
111 | * Translate String from source language to target language
112 | * @param $string
113 | * @param $sourceLanguage
114 | * @param $targetLanguage
115 | * @return mixed
116 | * @throws LocalizedException
117 | */
118 | public function translate($string, $sourceLanguage, $targetLanguage)
119 | {
120 | $client = $this->getClient();
121 | $request = $client->getRequest()
122 | ->setUri($this->config->getDeeplApiUrl() . 'translate')
123 | ->setMethod(\Laminas\Http\Request::METHOD_POST);
124 |
125 | if (!in_array($targetLanguage, self::AVAILABLE_LANGUAGES)) {
126 | throw new LocalizedException(__('Target Language is not available!'));
127 | }
128 |
129 | $text = $this->replaceDirectives($string);
130 |
131 | $post = $request->getPost();
132 |
133 | $post->set('text', $text)
134 | ->set('source_lang', $sourceLanguage)
135 | ->set('target_lang', $targetLanguage)
136 | ->set('tag_handling', $this->config->getTagHandling())
137 | ->set('preserve_formatting', 1)
138 | ->set('split_sentences', $this->config->getSplitSentences());
139 |
140 | if (in_array($targetLanguage, array('DE', 'FR', 'IT', 'ES', 'NL', 'PL', 'PT-PT', 'PT-BR', 'RU'))) {
141 | $post->set('formality', $this->config->getFormality());
142 | }
143 |
144 | $request->setPost($post);
145 | $result = $client->send($request);
146 |
147 | if ($this->config->isLogEnabled()) {
148 | $this->logger->info('Deepl Request: ', [$post]);
149 | $this->logger->info('Deepl Response: ', [$result]);
150 | }
151 |
152 | if ($this->_hasError($result)) {
153 | $this->_handleError($result);
154 | }
155 |
156 | $translate = json_decode($result->getBody(), true);
157 |
158 | if (!isset($translate['translations'][0]['text'])) {
159 | throw new LocalizedException(__('Translation is empty.'));
160 | }
161 |
162 | $translatedText = str_replace(['{{{', '}}}'], ['{{', '}}'], $translate['translations'][0]['text']);
163 |
164 | return $this->replacePlaceholders($translatedText);
165 | }
166 |
167 | /**
168 | * @return mixed
169 | * @throws LocalizedException
170 | */
171 | public function getUsage()
172 | {
173 | $client = $this->getClient();
174 | $request = $client->getRequest()
175 | ->setUri($this->config->getDeeplApiUrl() . 'usage')
176 | ->setMethod(Request::METHOD_GET);
177 |
178 | $query = $request->getQuery();
179 |
180 | $request->setQuery($query);
181 | $result = $client->send($request);
182 |
183 | if ($this->_hasError($result)) {
184 | $this->_handleError($result);
185 | }
186 |
187 | $usage = json_decode($result->getBody(), true);
188 |
189 | if (!isset($usage['character_count'])) {
190 | throw new LocalizedException(__('Usage is empty.'));
191 | }
192 |
193 | return $this->usage = $usage;
194 | }
195 |
196 | /**
197 | * @return int|false
198 | * @throws LocalizedException
199 | */
200 | public function getCharacterLimit()
201 | {
202 | if (!$this->usage) {
203 | try {
204 | $this->getUsage();
205 | } catch (LocalizedException $e) {
206 | $this->logger->error($e->getMessage());
207 | return false;
208 | }
209 | }
210 |
211 | if (!isset($this->usage['character_limit'])) {
212 | return 0;
213 | }
214 |
215 | return $this->usage['character_limit'];
216 | }
217 |
218 | /**
219 | * @return int|false
220 | * @throws LocalizedException
221 | */
222 | public function getCharacterCount()
223 | {
224 | if (empty($this->usage)) {
225 | try {
226 | $this->getUsage();
227 | } catch (LocalizedException $e) {
228 | $this->logger->error($e->getMessage());
229 | return false;
230 | }
231 | }
232 |
233 | if (!isset($this->usage['character_count'])) {
234 | return 0;
235 | }
236 |
237 | return $this->usage['character_count'];
238 | }
239 |
240 | /**
241 | * @param Response $response
242 | */
243 | protected function _hasError($response)
244 | {
245 | return $response->getStatusCode() != 200;
246 | }
247 |
248 | /**
249 | * @param Response $response
250 | * @throws LocalizedException
251 | */
252 | protected function _handleError($response)
253 | {
254 | $status = $response->getStatusCode();
255 | if ($status == 400) {
256 | throw new LocalizedException(__('Wrong request, please check error message and your parameters.'));
257 | } elseif ($status == 403) {
258 | throw new LocalizedException(__('Authorization failed. Please supply a valid auth_key parameter.'));
259 | } elseif ($status == 413) {
260 | throw new LocalizedException(__('Request Entity Too Large. The request size exceeds the current limit.'));
261 | } elseif ($status == 429) {
262 | throw new LocalizedException(__('Too many requests. Please wait and send your request once again.'));
263 | } elseif ($status == 456) {
264 | throw new LocalizedException(__('Quota exceeded. The character limit has been reached.'));
265 | } else {
266 | throw new LocalizedException(__('Status %1. %2.', $status, $response->getReasonPhrase()));
267 | }
268 | }
269 |
270 | /**
271 | * @return Client
272 | */
273 | private function getClient(): Client
274 | {
275 | return $this->client->setHeaders([
276 | 'Authorization' => 'DeepL-Auth-Key ' . $this->config->getDeeplApiKey(),
277 | ])->setOptions(
278 | [
279 | 'timeout' => $this->config->getTimeout()
280 | ]
281 | );
282 | }
283 |
284 | private function replaceDirectives($value)
285 | {
286 | foreach ($this->directiveProcessors as $directiveProcessor) {
287 | if (!$directiveProcessor instanceof DirectiveProcessorInterface) {
288 | throw new \InvalidArgumentException(
289 | 'Directive processors must implement ' . DirectiveProcessorInterface::class
290 | );
291 | }
292 |
293 | $pattern = $directiveProcessor->getRegularExpression();
294 |
295 | if (preg_match_all($pattern, $value, $constructions, PREG_SET_ORDER)) {
296 | foreach ($constructions as $construction) {
297 | if (!empty($construction[0])) {
298 | $replaceName = '#'.uniqid().'#';
299 | $this->directives[$replaceName] = $construction[0];
300 | $value = str_replace($construction[0], $replaceName, $value);
301 | }
302 | }
303 | }
304 | }
305 |
306 | return $value;
307 | }
308 |
309 | private function replacePlaceholders($translatedString)
310 | {
311 | foreach ($this->directives as $replaceName => $directive) {
312 | $translatedString = str_replace($replaceName, $directive, $translatedString);
313 | }
314 |
315 | return $translatedString;
316 | }
317 | }
318 |
--------------------------------------------------------------------------------
/Helper/Config.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2017 aromicon GmbH (http://www.aromicon.de)
7 | * @license http://opensource.org/licenses/gpl-3.0 GNU General Public License, version 3 (GPLv3)
8 | */
9 | namespace Aromicon\Deepl\Helper;
10 |
11 | use Aromicon\Deepl\Model\System\Config\Version;
12 | use Magento\Framework\App\Helper\Context;
13 | use Magento\Framework\Locale\Bundle\LanguageBundle;
14 | use Magento\Framework\Locale\Bundle\RegionBundle;
15 |
16 | class Config extends \Magento\Framework\App\Helper\AbstractHelper
17 | {
18 | const XML_PATH_DEFAULT_LOCALE = 'general/locale/code';
19 | const XML_PATH_DEFAULT_STORE = 'deepl/general/store';
20 | const XML_PATH_DEFAULT_SPLIT_SENTENCE = 'deepl/api/split_sentence';
21 | const XML_PATH_DEFAULT_FORMALITY = 'deepl/api/formality';
22 | const XML_PATH_DEEPL_API_URL = 'deepl/api/url';
23 | const XML_PATH_DEEPL_API_URL_FREE = 'deepl/api/url_free';
24 | const XML_PATH_DEEPL_API_VERSION = 'deepl/api/version';
25 | const XML_PATH_DEEPL_API_KEY = 'deepl/api/key';
26 | const XML_PATH_DEEPL_CMS_BLOCK_FIELDS = 'deepl/cms/block_fields';
27 | const XML_PATH_DEEPL_CMS_PAGE_FIELDS = 'deepl/cms/page_fields';
28 | const XML_PATH_DEEPL_PRODUCT_FIELDS = 'deepl/product/product_fields';
29 | const XML_PATH_DEEPL_CATEGORY_FIELDS = 'deepl/category/category_fields';
30 | const XML_PATH_DEEPL_LOG_ENABLE = 'deepl/log/enable_log';
31 | const XML_PATH_DEEPL_TIMEOUT = 'deepl/api/timeout';
32 | const XML_PATH_DEEPL_TAG_HANDLING = 'deepl/api/tag_handling';
33 |
34 | /**
35 | * @var \Aromicon\Deepl\Model\System\Config\PageFields
36 | */
37 | private $pageFields;
38 |
39 | /**
40 | * @var \Aromicon\Deepl\Model\System\Config\ProductFields
41 | */
42 | private $productFields;
43 |
44 | /**
45 | * @var \Aromicon\Deepl\Model\System\Config\ProductFields
46 | */
47 | private $categoryFields;
48 |
49 | public function __construct(
50 | Context $context,
51 | \Aromicon\Deepl\Model\System\Config\PageFields $pageFields,
52 | \Aromicon\Deepl\Model\System\Config\ProductFields $productFields,
53 | \Aromicon\Deepl\Model\System\Config\CategoryFields $categoryFields
54 | ) {
55 | $this->pageFields = $pageFields;
56 | $this->productFields = $productFields;
57 | $this->categoryFields = $categoryFields;
58 | parent::__construct($context);
59 | }
60 |
61 | /**
62 | * Get Battery Deposit is included in Product Price
63 | * @return bool
64 | */
65 | public function getStoreLanguage($store = null)
66 | {
67 | $locale = $this->scopeConfig->getValue(
68 | self::XML_PATH_DEFAULT_LOCALE,
69 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
70 | $store
71 | );
72 |
73 | $currentLocale = 'en';
74 | $languages = (new LanguageBundle())->get($currentLocale)['Languages'];
75 |
76 | $language = \Locale::getPrimaryLanguage($locale);
77 |
78 | return $languages[$language];
79 | }
80 |
81 | /**
82 | * @param $storeId
83 | * @return mixed|null|string|string[]
84 | */
85 | public function getLanguageCodeByStoreId($storeId, $isTarget = false)
86 | {
87 | $language = $this->scopeConfig->getValue(
88 | self::XML_PATH_DEFAULT_LOCALE,
89 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
90 | $storeId
91 | );
92 |
93 | if ($isTarget) {
94 | if ($language == 'en_GB') {
95 | return 'EN-GB';
96 | } elseif(str_starts_with($language, 'en')) {
97 | return 'EN-US';
98 | }
99 |
100 | //Switch for Portuguese
101 | if ($language == 'pt_BR') {
102 | return 'PT-BR';
103 | } elseif(str_starts_with($language, 'pt')) {
104 | return 'PT-PT';
105 | }
106 | }
107 |
108 | if ($language == 'zh_Hans_CN') {
109 | return 'ZH-HANS';
110 | } elseif($language == 'zh_Hant_TW' || $language == 'zh_Hant_HK') {
111 | return 'ZH-HANT';
112 | }
113 |
114 | return mb_strtoupper(mb_substr($language, 0, 2));
115 | }
116 |
117 | /**
118 | * @return mixed|null|string|string[]
119 | */
120 | public function getSourceStoreId($storeId = null)
121 | {
122 | $storeId = $this->scopeConfig->getValue(
123 | self::XML_PATH_DEFAULT_STORE,
124 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
125 | $storeId
126 | );
127 |
128 | return $storeId;
129 | }
130 |
131 | /**
132 | * @return mixed|null|string|string[]
133 | */
134 | public function getSourceLanguage($storeId = null)
135 | {
136 | $storeId = $this->getSourceStoreId($storeId);
137 | return $this->getLanguageCodeByStoreId($storeId);
138 | }
139 |
140 | /**
141 | * @return mixed
142 | */
143 | public function getDeeplApiUrl()
144 | {
145 | if ($this->getDeeplApiVersion() == Version::FREE) {
146 | return $this->scopeConfig->getValue(
147 | self::XML_PATH_DEEPL_API_URL_FREE
148 | );
149 | }
150 |
151 | return $this->scopeConfig->getValue(
152 | self::XML_PATH_DEEPL_API_URL
153 | );
154 | }
155 |
156 | /**
157 | * @param null $storeId
158 | * @return mixed
159 | */
160 | public function getDeeplApiVersion($storeId = null)
161 | {
162 | return $this->scopeConfig->getValue(
163 | self::XML_PATH_DEEPL_API_VERSION,
164 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
165 | $storeId
166 | );
167 | }
168 |
169 | /**
170 | * @param null $storeId
171 | * @return bool
172 | */
173 | public function hasApiKey($storeId = null)
174 | {
175 | return !empty($this->getDeeplApiKey($storeId));
176 | }
177 |
178 | /**
179 | * @param null $storeId
180 | * @return mixed
181 | */
182 | public function getDeeplApiKey($storeId = null)
183 | {
184 | return $this->scopeConfig->getValue(
185 | self::XML_PATH_DEEPL_API_KEY,
186 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
187 | $storeId
188 | );
189 | }
190 |
191 | /**
192 | * @return array|mixed
193 | */
194 | public function getTranslatableBlockFields()
195 | {
196 | $fields = $this->scopeConfig->getValue(
197 | self::XML_PATH_DEEPL_CMS_BLOCK_FIELDS,
198 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
199 | );
200 |
201 | if (empty($fields)) {
202 | $fields = [];
203 | foreach ($this->pageFields->toOptionArray() as $item) {
204 | $fields[] = $item['value'];
205 | };
206 | } else {
207 | $fields = explode(',', $fields);
208 | }
209 |
210 | return $fields;
211 | }
212 |
213 | /**
214 | * @return array|mixed
215 | */
216 | public function getTranslatablePageFields()
217 | {
218 | $fields = $this->scopeConfig->getValue(
219 | self::XML_PATH_DEEPL_CMS_PAGE_FIELDS,
220 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
221 | );
222 |
223 | if (empty($fields)) {
224 | $fields = [];
225 | foreach ($this->pageFields->toOptionArray() as $item) {
226 | $fields[] = $item['value'];
227 | };
228 | } else {
229 | $fields = explode(',', $fields);
230 | }
231 |
232 | return $fields;
233 | }
234 |
235 | /**
236 | * @return array|mixed
237 | */
238 | public function getTranslatableProductFields()
239 | {
240 | $fields = $this->scopeConfig->getValue(
241 | self::XML_PATH_DEEPL_PRODUCT_FIELDS,
242 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
243 | );
244 |
245 | if (empty($fields)) {
246 | $fields = [];
247 | foreach ($this->pageFields->toOptionArray() as $item) {
248 | $fields[] = $item['value'];
249 | };
250 | } else {
251 | $fields = explode(',', $fields);
252 | }
253 |
254 | return $fields;
255 | }
256 |
257 | /**
258 | * @return array|mixed
259 | */
260 | public function getTranslatableCategoryFields()
261 | {
262 | $fields = $this->scopeConfig->getValue(
263 | self::XML_PATH_DEEPL_CATEGORY_FIELDS,
264 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
265 | );
266 |
267 | if (empty($fields)) {
268 | $fields = [];
269 | foreach ($this->pageFields->toOptionArray() as $item) {
270 | $fields[] = $item['value'];
271 | };
272 | } else {
273 | $fields = explode(',', $fields);
274 | }
275 |
276 | return $fields;
277 | }
278 |
279 | /**
280 | * @return mixed
281 | */
282 | public function isLogEnabled()
283 | {
284 | return $this->scopeConfig->getValue(
285 | self::XML_PATH_DEEPL_LOG_ENABLE,
286 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
287 | );
288 | }
289 |
290 | /**
291 | * @return mixed
292 | */
293 | public function getSplitSentences()
294 | {
295 | return $this->scopeConfig->getValue(
296 | self::XML_PATH_DEFAULT_SPLIT_SENTENCE,
297 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
298 | );
299 | }
300 |
301 | /**
302 | * @return mixed
303 | */
304 | public function getFormality()
305 | {
306 | $formality = $this->scopeConfig->getValue(
307 | self::XML_PATH_DEFAULT_FORMALITY,
308 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
309 | );
310 |
311 | if (empty($formality)) {
312 | $formality = 'default';
313 | }
314 |
315 | return $formality;
316 | }
317 |
318 | /**
319 | * @return int
320 | */
321 | public function getTimeout()
322 | {
323 | $value = (int) $this->scopeConfig->getValue(
324 | self::XML_PATH_DEEPL_TIMEOUT,
325 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
326 | );
327 | return $value > 0 ? $value : 30;
328 | }
329 |
330 | /**
331 | * @return string
332 | */
333 | public function getTagHandling()
334 | {
335 | $value = $this->scopeConfig->getValue(
336 | self::XML_PATH_DEEPL_TAG_HANDLING,
337 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
338 | );
339 |
340 | return !empty($value) ? $value : 'xml';
341 | }
342 | }
343 |
--------------------------------------------------------------------------------