W#@`#W#X#@$@#PX#`X#@$p(#xX#X#@$-#X#X#@$>$X#X#@$8I$ X#@_#8X#HX#@$@o#X#X#@>$X#X#@8I$X#@Q# X#0X#@$x5#HX#`X#@$U#xX#X#P$X#@$8I$X#@#X#X#@&#0X#HX#@ W#`X#xX#@>$X#X#@8I$X#$X#@$H7#X#0X#$HX#`X#@8I$X#@$ #X#X#@$@a0#X#X#@$#$# V#`X#HX#xX#@$8I$X#@T#X#X#@Y6#X#X#@ #X#(X#$$H$#8I$X#@W#X#X#@P&#X#X#@@#X#(X#@X#@$5#XX#pX#@$8I$$#X#X#@x`#X#X#@#X#(X#@#@X#XX#@8I$X#@$#X#X#@$P4#$$X# X#@$0 >$( X#@ X#@$8I$p X#@`V# X# X#@b-# X# X#@x^ $ X# X#@N#H$#X X#@$@U#p X# X#@$P$# X# X#@$-# X# X#@$`U# X# X#@U8I$@ X#@ S#$# X# X#@'# X# X#@# X# X#@8I$( X#@$V#@ X#P X#@$P#h X# X#@$h3# $#V# X# X#@$8I$ X#@@T#( X#8 X#@`#P X#h X#@^# X# X#@>$ X# X#@ $8$ X#@$0 #8X#PX#@$`S#hX#X#@$@#X#X#@$8I$X#@N#X#X#@ $$$p $PX#hX#@$8I$X#@`N#X#( $updatedPackages[ $package->ID ] ) ) { return; } $updatedPackages[ $package->ID ] = true; $shouldTranslate = $this->packageDefinitionQuery->isPackageOnTheList( $package->kind_slug ); /** * Allows enabling automatic translation for string packages. * * @since 4.7.0 * * @param bool $shouldTranslate * @param array $packageData { * @type string $name * @type string $kind * @type string $kind_slug * } */ if ( apply_filters( 'wpml_auto_translate_string_package', $shouldTranslate, (array) $package ) ) { Hooks::onAction( 'shutdown' ) ->then( $this->getPackageHandler( $package ) ); } } /** * @param \WPML_Package $package * * @return \Closure */ private function getPackageHandler( \WPML_Package $package ) { return function() use ( $package ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $packageElement = $this->translationElementFactory->create_package( $package->ID, $package->kind_slug ); if ( $packageElement->get_language_code() === Languages::getDefaultCode() && $packageElement->get_source_language_code() === null ) { $secondaryLanguageCodes = LanguageMappings::geCodesEligibleForAutomaticTranslations(); // @todo: When $secondaryLanguageCodes is empty this can mean that WPML failed to get languages eligible for automatic translation // from ATE side, we should warn the user as we do for posts. $this->cancelExistingTranslationJobs( $packageElement, $secondaryLanguageCodes ); $this->createTranslationJobs( $packageElement, $secondaryLanguageCodes ); } }; } /** * @param \WPML_Translation_Element $translationElement * @param array $languages */ private function cancelExistingTranslationJobs( \WPML_Translation_Element $translationElement, $languages ) { $getJobEntity = function ( $jobId ) use ( $translationElement ) { return wpml_tm_get_jobs_repository()->get_job( Map::fromJobId( $jobId ), $translationElement->get_element_type() ); }; wpml_collect( $languages ) ->map( Jobs::getElementJob( $translationElement->get_element_id(), $translationElement->get_wpml_element_type() ) ) ->filter() ->reject( self::isCompleteAndUpToDateJob() ) ->map( Obj::prop( 'job_id' ) ) ->map( Jobs::clearReviewStatus() ) ->map( Jobs::setNotTranslatedStatus() ) ->map( Jobs::clearTranslated() ) ->map( $getJobEntity ) ->map( Fns::tap( partial( 'do_action', 'wpml_tm_job_cancelled' ) ) ); } /** * @return callable :: \stdClass -> bool */ private static function isCompleteAndUpToDateJob() { return function ( $job ) { return Cast::toInt( $job->needs_update ) !== 1 && Cast::toInt( $job->status ) === ICL_TM_COMPLETE; }; } /** * @param \WPML_Translation_Element $translationElement * @param array $targetLanguages * * @return void */ public function createTranslationJobs( \WPML_Translation_Element $translationElement, $targetLanguages ) { if ( ! Option::shouldTranslateEverything() ) { return; } $isNotCompleteAndUpToDate = Logic::complement( self::isCompleteAndUpToDateJob() ); $sendToTranslation = function ( $language ) use ( $translationElement, $isNotCompleteAndUpToDate ) { /** @var \stdClass|false $job */ $job = Jobs::getElementJob( $translationElement->get_element_id(), $translationElement->get_wpml_element_type(), $language ); if ( ! $job || ( $isNotCompleteAndUpToDate( $job ) && $this->canJobBeReTranslatedAutomatically( $job->job_id ) ) ) { $this->createJob( $translationElement, $language ); } }; Fns::map( $sendToTranslation, $targetLanguages ); } /** * @param int $jobId * * @return bool */ private function canJobBeReTranslatedAutomatically( $jobId ) { return wpml_tm_load_old_jobs_editor()->get( $jobId ) === \WPML_TM_Editors::ATE; } /** * @param \WPML_Translation_Element $translationElement * @param string $language */ private function createJob( \WPML_Translation_Element $translationElement, $language ) { $batch = new \WPML_TM_Translation_Batch( [ new \WPML_TM_Translation_Batch_Element( $translationElement->get_element_id(), $translationElement->get_element_type(), $translationElement->get_language_code(), [ $language => 1 ] ), ], \TranslationProxy_Batch::get_generic_batch_name( true ), [ $language => User::getCurrentId() ] ); wpml_load_core_tm()->send_jobs( $batch, $translationElement->get_element_type(), Jobs::SENT_AUTOMATICALLY ); } /** * @param string $sourceLanguage * @param array $elements E.g. [ [1, 'fr'], [1, 'de'], [2, 'fr'] ] * @param string $elementType Element type 'post_page' or 'package_wpforms' or 'st-batch' * * @return array */ public function createNewTranslationJobs( $sourceLanguage, array $elements, $elementType ) { $getTargetLang = Lst::nth( 1 ); $setTranslateAction = Obj::objOf( Fns::__, \TranslationManagement::TRANSLATE_ELEMENT_ACTION ); $setTranslatorId = Obj::objOf( Fns::__, User::getCurrentId() ); $wpmlType = 'post'; if ( $elementType === 'st-batch' ) { $wpmlType = 'st-batch'; } else if ( Str::startsWith( 'package_', $elementType ) ) { $wpmlType = 'package'; } $targetLanguages = \wpml_collect( $elements ) ->map( $getTargetLang ) ->unique() ->mapWithKeys( $setTranslatorId ) ->toArray(); $makeBatchElement = function ( $targetLanguages, $postId ) use ( $sourceLanguage, $wpmlType ) { return new \WPML_TM_Translation_Batch_Element( $postId, $wpmlType, $sourceLanguage, $targetLanguages->toArray() ); }; $batchElements = \wpml_collect( $elements ) ->groupBy( 0 ) ->map( Fns::map( $getTargetLang ) ) ->map( invoke( 'mapWithKeys' )->with( $setTranslateAction ) ) ->map( $makeBatchElement ) ->values() ->toArray(); $batch = new \WPML_TM_Translation_Batch( $batchElements, \TranslationProxy_Batch::get_generic_batch_name( true ), $targetLanguages ); $batch->setTranslationMode( 'auto' ); wpml_load_core_tm()->send_jobs( $batch, $wpmlType, Jobs::SENT_AUTOMATICALLY ); $getJobId = pipe( Fns::converge( Jobs::getElementJob(), [ Obj::prop( 'elementId' ), Obj::prop( 'elementType' ), Obj::prop( 'lang' ) ] ), Obj::prop( 'job_id' ), Fns::unary( 'intval' ) ); return \wpml_collect( $elements ) ->map( Lst::zipObj( [ 'elementId', 'lang' ] ) ) ->map( Obj::addProp( 'elementType', Fns::always( $elementType === 'st-batch' ? 'st-batch_strings' : $elementType ) ) ) ->map( Obj::addProp( 'jobId', $getJobId ) ) ->toArray(); } }