diff --git a/Controller/Adminhtml/Mass/Translate/Locked.php b/Controller/Adminhtml/Mass/Translate/Locked.php index 3198948..3e934d0 100644 --- a/Controller/Adminhtml/Mass/Translate/Locked.php +++ b/Controller/Adminhtml/Mass/Translate/Locked.php @@ -22,7 +22,8 @@ public function execute() $this->messageManager->addNotice( __( - 'This option is available in Magefan Translation Extra plan only. Please upgrade at ' .$url. '.', + 'This option is available in Magefan Translation Extra plan only. + Please upgrade plan to use this feature.', $url . $params ) ); diff --git a/Model/Config/Source/ScheduleSource.php b/Model/Config/Source/ScheduleSource.php index b651fa1..7ac267e 100644 --- a/Model/Config/Source/ScheduleSource.php +++ b/Model/Config/Source/ScheduleSource.php @@ -39,6 +39,8 @@ public function toOptionArray() ['value' => EntityManager::SECONDBLOG_CATEGORY_ID, 'label' => __('Magefan Second Blog Category')], ['value' => EntityManager::SECONDBLOG_AUTHOR_ID, 'label' => __('Magefan Second Blog Author')], + ['value' => EntityManager::REVIEW_ID, 'label' => __('Product Review')], + ['value' => EntityManager::TRANSLATE_ID, 'label' => __('Phrases from Search And Translate')] ]; diff --git a/Model/EntityManager.php b/Model/EntityManager.php index f770a49..aa83f1f 100644 --- a/Model/EntityManager.php +++ b/Model/EntityManager.php @@ -28,6 +28,8 @@ class EntityManager public const SECONDBLOG_CATEGORY_ID = 13; public const SECONDBLOG_AUTHOR_ID = 14; + public const REVIEW_ID = 15; + public const TYPE_CATEGORY = 'category'; public const TYPE_PRODUCT = 'product'; public const TYPE_PAGE = 'page'; @@ -45,6 +47,8 @@ class EntityManager public const TYPE_SECONDBLOG_CATEGORY = 'secondblog_category'; public const TYPE_SECONDBLOG_AUTHOR = 'secondblog_author'; + public const TYPE_REVIEW = 'review'; + public const TYPES = [ self::TYPE_PRODUCT => self::PRODUCT_ID, self::TYPE_CATEGORY => self::CATEGORY_ID, @@ -61,7 +65,9 @@ class EntityManager self::TYPE_SECONDBLOG_POST => self::SECONDBLOG_POST_ID, self::TYPE_SECONDBLOG_TAG => self::SECONDBLOG_TAG_ID, self::TYPE_SECONDBLOG_CATEGORY => self::SECONDBLOG_CATEGORY_ID, - self::TYPE_SECONDBLOG_AUTHOR => self::SECONDBLOG_AUTHOR_ID + self::TYPE_SECONDBLOG_AUTHOR => self::SECONDBLOG_AUTHOR_ID, + + self::TYPE_REVIEW => self::REVIEW_ID ]; /** diff --git a/Model/TranslatableData.php b/Model/TranslatableData.php index 9b21b73..c6d6361 100644 --- a/Model/TranslatableData.php +++ b/Model/TranslatableData.php @@ -136,6 +136,10 @@ public function getList(?string $type = null): array $data[EntityManager::TYPE_SECONDBLOG_AUTHOR] = $this->getBlogAuthorFields(); break; + case EntityManager::TYPE_REVIEW: + $data[EntityManager::TYPE_REVIEW] = $this->getReviewFields(); + break; + default: // If no type or unrecognized type is passed, return all $data[EntityManager::TYPE_CATEGORY] = $this->getCatalogAttributes($this->categoryAttributeRepository); @@ -157,6 +161,10 @@ public function getList(?string $type = null): array $data[EntityManager::TYPE_SECONDBLOG_AUTHOR] = $this->getBlogAuthorFields(); } + if ($this->moduleManager->isEnabled('Magento_Review')) { + $data[EntityManager::TYPE_REVIEW] = $this->getReviewFields(); + } + break; } @@ -351,6 +359,23 @@ private function getBlogCategoryFields(): array ]; } + /** + * Product review fields. + * + * Nickname is intentionally not listed - it holds the reviewer's name, + * which must not be machine translated. It is still stored per store view + * so it can be corrected manually. + * + * @return array[] + */ + private function getReviewFields(): array + { + return [ + ['label' => __('Summary of Review'), 'code' => 'title', 'type' => 'text'], + ['label' => __('Review'), 'code' => 'detail', 'type' => 'text'] + ]; + } + /** * @return array[] */ diff --git a/Plugin/Backend/Magento/Backend/Block/Widget/Grid/Massaction.php b/Plugin/Backend/Magento/Backend/Block/Widget/Grid/Massaction.php index ef168e9..6e2ca3a 100644 --- a/Plugin/Backend/Magento/Backend/Block/Widget/Grid/Massaction.php +++ b/Plugin/Backend/Magento/Backend/Block/Widget/Grid/Massaction.php @@ -24,6 +24,8 @@ class Massaction 'secondblog_category_index', 'secondblog_tag_index', 'secondblogauthor_author_index', + 'review_product_index', + 'review_product_pending', ]; /** diff --git a/Plugin/Backend/Magento/Review/Block/Adminhtml/Edit.php b/Plugin/Backend/Magento/Review/Block/Adminhtml/Edit.php new file mode 100644 index 0000000..d783e66 --- /dev/null +++ b/Plugin/Backend/Magento/Review/Block/Adminhtml/Edit.php @@ -0,0 +1,68 @@ +config = $config; + } + + /** + * @param \Magento\Review\Block\Adminhtml\Edit $subject + * @param \Magento\Framework\View\Layout $layout + * @return array + */ + public function beforeSetLayout( + \Magento\Review\Block\Adminhtml\Edit $subject, + $layout + ) { + if ($this->config->isEnabled() && $subject->getRequest()->getParam('id')) { + $subject->addButton( + 'mftranslation_locked_button', + [ + 'label' => __('Auto Translate'), + 'on_click' => $this->getOnClick(), + 'class' => 'mf_auto_translate', + ], + 10 + ); + } + + return [$layout]; + } + + /** + * @return string + */ + private function getOnClick(): string + { + return "require(['Magefan_Translation/js/mf-upgrade-plan-popup'], function(mfPopup){" + . "mfPopup('Extra', 'auto-translate', 'button');" + . "});"; + } +} diff --git a/Plugin/Backend/Magento/Review/Block/Adminhtml/Edit/FormPlugin.php b/Plugin/Backend/Magento/Review/Block/Adminhtml/Edit/FormPlugin.php new file mode 100644 index 0000000..42918af --- /dev/null +++ b/Plugin/Backend/Magento/Review/Block/Adminhtml/Edit/FormPlugin.php @@ -0,0 +1,183 @@ +config = $config; + $this->mfSecureRenderer = $mfSecureRenderer; + } + + /** + * @param \Magento\Review\Block\Adminhtml\Edit\Form $subject + * @param \Magento\Framework\Data\Form|null $form + * @return \Magento\Framework\Data\Form|null + */ + public function afterGetForm($subject, $form) + { + if (!$form || !$this->config->isEnabled()) { + return $form; + } + + $this->addLockedExcludeAutoTranslationField($form); + + return $form; + } + + /** + * Adds the "Auto Translation (Extra)" fieldset right after review_details, or + * returns null without touching the form if it's already there (getForm() runs + * more than once per page render) or review_details itself isn't present to + * insert after. + * + * Shared between this class's own locked field below and + * Magefan\TranslationPlus\...\FormPlugin's real one, so the guard only lives once. + * + * @param \Magento\Framework\Data\Form $form + * @return \Magento\Framework\Data\Form\Element\Fieldset|null + */ + protected function addAutoTranslationFieldset($form) + { + if (!$form->getElement('review_details') || $form->getElement('mf_auto_translation')) { + return null; + } + + return $form->addFieldset( + 'mf_auto_translation', + ['legend' => __('Auto Translation (Extra)')], + 'review_details' + ); + } + + /** + * Adds the locked "Exclude From Auto Translation" field: the same toggle a working + * install would show, disabled, with a click-anywhere overlay that opens the + * upgrade popup instead of doing anything. + * + * @param \Magento\Framework\Data\Form $form + * @return void + */ + protected function addLockedExcludeAutoTranslationField($form) + { + $fieldset = $this->addAutoTranslationFieldset($form); + + if (!$fieldset) { + return; + } + + $fieldset->addField( + 'mf_exclude_auto_translation', + 'note', + [ + 'label' => __('Exclude From Auto Translation'), + 'text' => $this->getLockedToggleHtml(), + ] + ); + } + + /** + * Renders a locked stand-in for a toggle-switch field: the same toggle + + * "Use Default Value" markup the real, working field would use, both inert, with a + * transparent overlay on top that shows the upgrade popup on any click. + * + * @return string + */ + private function getLockedToggleHtml() + { + $yes = $this->escapeAttr(__('Yes')); + $no = $this->escapeAttr(__('No')); + + return '