diff --git a/composer.json b/composer.json
index c81c2cc5df..bc79955492 100644
--- a/composer.json
+++ b/composer.json
@@ -26,6 +26,7 @@
"stevenmaguire/oauth2-microsoft": "^2.2",
"league/oauth2-github": "^3.1",
"league/oauth2-facebook": "^2.2",
+ "translated/lara-sdk":"^1.0.1",
"psr/log": "~1.0",
"ext-curl": "*",
"ext-pcntl": "*",
diff --git a/composer.lock b/composer.lock
index e96caf4887..4425b71b4e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "4879d1c070ae9d3f12f01f7c31efd172",
+ "content-hash": "c107c1842a725b53940e15bd728aa088",
"packages": [
{
"name": "aws/aws-crt-php",
@@ -3978,6 +3978,50 @@
}
],
"time": "2024-11-10T20:33:58+00:00"
+ },
+ {
+ "name": "translated/lara-sdk",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/translated/lara-php.git",
+ "reference": "acd4a794550f25b65dc5dd33e75444d347a4c3b4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/translated/lara-php/zipball/acd4a794550f25b65dc5dd33e75444d347a4c3b4",
+ "reference": "acd4a794550f25b65dc5dd33e75444d347a4c3b4",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "ext-json": "*",
+ "php": ">=5.6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Lara\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Translated",
+ "email": "info@translated.com",
+ "homepage": "https://translated.com/"
+ }
+ ],
+ "description": "Official Lara SDK for PHP",
+ "homepage": "https://github.com/translated/lara-php",
+ "support": {
+ "issues": "https://github.com/translated/lara-php/issues",
+ "source": "https://github.com/translated/lara-php/tree/v1.0.1"
+ },
+ "time": "2024-12-03T21:47:29+00:00"
}
],
"packages-dev": [
@@ -6319,7 +6363,7 @@
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
@@ -6340,6 +6384,6 @@
"ext-iconv": "*",
"ext-openssl": "*"
},
- "platform-dev": [],
+ "platform-dev": {},
"plugin-api-version": "2.6.0"
}
diff --git a/docker b/docker
index bd604269bc..a67a0aaa32 160000
--- a/docker
+++ b/docker
@@ -1 +1 @@
-Subproject commit bd604269bc38a9e9715c1a38ae3b0e11f7ea472e
+Subproject commit a67a0aaa32f2f4a241a28fee1e2957be9eaaa7e6
diff --git a/inc/INIT.php b/inc/INIT.php
index 7f2206ebba..954b2c5924 100644
--- a/inc/INIT.php
+++ b/inc/INIT.php
@@ -155,7 +155,6 @@ class INIT {
* @var int Interval in seconds
*/
public static $COPY_SOURCE_INTERVAL = 300;
- public static $MAX_NUM_SEGMENTS = 500;
/**
* Default Matecat user agent string
@@ -205,6 +204,11 @@ class INIT {
*/
public static $DEFAULT_TM_KEY = '';
+ /**
+ * @var string The default MMT license is applied when Lara falls back for unsupported languages and the user does not add their personal MMT license.
+ */
+ public static $DEFAULT_MMT_KEY = '';
+
public static $ENABLED_BROWSERS = [ 'applewebkit', 'chrome', 'safari', 'edge', 'firefox' ];
/**
diff --git a/lib/Controller/catController.php b/lib/Controller/catController.php
index 9beda244eb..4586c710e9 100644
--- a/lib/Controller/catController.php
+++ b/lib/Controller/catController.php
@@ -186,16 +186,17 @@ public function doAction() {
$active_mt_engine_array = [];
if ( !empty( $active_mt_engine ) ) {
+ $engine_type = explode("\\", $active_mt_engine[ 0 ]->class_load);
$active_mt_engine_array = [
"id" => $active_mt_engine[ 0 ]->id,
"name" => $active_mt_engine[ 0 ]->name,
"type" => $active_mt_engine[ 0 ]->type,
"description" => $active_mt_engine[ 0 ]->description,
- 'engine_type' => ( $active_mt_engine[ 0 ]->class_load === 'MyMemory' ? 'MMTLite' : $active_mt_engine[ 0 ]->class_load ),
+ 'engine_type' => ( $active_mt_engine[ 0 ]->class_load === 'MyMemory' ? 'MMTLite' : array_pop($engine_type) ),
];
}
- $this->template->active_engine = Utils::escapeJsonEncode( $active_mt_engine_array );
+ $this->template->active_engine = $active_mt_engine_array;
/*
* array_unique cast EnginesModel_EngineStruct to string
@@ -380,7 +381,6 @@ public function setTemplateVars() {
$this->template->mt_engines = $this->translation_engines;
$this->template->translation_engines_intento_providers = Intento::getProviderList();
- $this->template->translation_engines_intento_prov_json = Utils::escapeJsonEncode( Intento::getProviderList() );
$this->template->not_empty_default_tm_key = !empty( INIT::$DEFAULT_TM_KEY );
@@ -412,7 +412,6 @@ public function setTemplateVars() {
$this->template->maxTMXFileSize = INIT::$MAX_UPLOAD_TMX_FILE_SIZE;
$this->template->tagLockCustomizable = ( INIT::$UNLOCKABLE_TAGS == true ) ? true : false;
- $this->template->maxNumSegments = INIT::$MAX_NUM_SEGMENTS;
$this->template->copySourceInterval = INIT::$COPY_SOURCE_INTERVAL;
/*
diff --git a/lib/Controller/engineController.php b/lib/Controller/engineController.php
index dea4c703a6..0bdad93399 100755
--- a/lib/Controller/engineController.php
+++ b/lib/Controller/engineController.php
@@ -1,6 +1,10 @@
[ 'getTermList' ] // letsmt no longer requires this function. it's left as an example
+ // 'letsmt' => [ 'getTermList' ] // letsmt no longer requires this function. it's left as an example
];
public function __construct() {
@@ -126,7 +130,7 @@ private function add() {
$newEngineStruct->extra_parameters[ 'DeepL-Auth-Key' ] = $this->engineData[ 'client_id' ];
try {
- DeepLValidator::validate($newEngineStruct);
+ DeepLValidator::validate( $newEngineStruct );
} catch ( Exception $e ) {
$this->result[ 'errors' ][] = [ 'code' => $e->getCode(), 'message' => $e->getMessage() ];
@@ -143,11 +147,11 @@ private function add() {
*/
$newEngineStruct = EnginesModel_MicrosoftHubStruct::getStruct();
- $newEngineStruct->name = $this->name;
- $newEngineStruct->uid = $this->user->uid;
- $newEngineStruct->type = Constants_Engines::MT;
- $newEngineStruct->extra_parameters[ 'client_id' ] = $this->engineData[ 'client_id' ];
- $newEngineStruct->extra_parameters[ 'category' ] = $this->engineData[ 'category' ];
+ $newEngineStruct->name = $this->name;
+ $newEngineStruct->uid = $this->user->uid;
+ $newEngineStruct->type = Constants_Engines::MT;
+ $newEngineStruct->extra_parameters[ 'client_id' ] = $this->engineData[ 'client_id' ];
+ $newEngineStruct->extra_parameters[ 'category' ] = $this->engineData[ 'category' ];
break;
case strtolower( Constants_Engines::APERTIUM ):
@@ -221,28 +225,42 @@ private function add() {
break;
- case strtolower(Constants_Engines::INTENTO):
+ case strtolower( Constants_Engines::INTENTO ):
/**
* Create a record of type Intento
*/
- $newEngineStruct = EnginesModel_IntentoStruct::getStruct();
- $newEngineStruct->name = $this->name;
- $newEngineStruct->uid = $this->user->uid;
- $newEngineStruct->type = Constants_Engines::MT;
- $newEngineStruct->extra_parameters['apikey'] = $this->engineData['secret'];
- $newEngineStruct->extra_parameters['provider'] = $this->engineData['provider'];
- $newEngineStruct->extra_parameters['providerkey'] = $this->engineData['providerkey'];
- $newEngineStruct->extra_parameters['providercategory'] = $this->engineData['providercategory'];
+ $newEngineStruct = EnginesModel_IntentoStruct::getStruct();
+ $newEngineStruct->name = $this->name;
+ $newEngineStruct->uid = $this->user->uid;
+ $newEngineStruct->type = Constants_Engines::MT;
+ $newEngineStruct->extra_parameters[ 'apikey' ] = $this->engineData[ 'secret' ];
+ $newEngineStruct->extra_parameters[ 'provider' ] = $this->engineData[ 'provider' ];
+ $newEngineStruct->extra_parameters[ 'providerkey' ] = $this->engineData[ 'providerkey' ];
+ $newEngineStruct->extra_parameters[ 'providercategory' ] = $this->engineData[ 'providercategory' ];
+ break;
+
+ case strtolower( Constants_Engines::LARA ):
+ /**
+ * Create a record of type Lara
+ */
+ $newEngineStruct = LaraStruct::getStruct();
+
+ $newEngineStruct->uid = $this->user->uid;
+ $newEngineStruct->type = Constants_Engines::MT;
+ $newEngineStruct->extra_parameters[ 'Lara-AccessKeyId' ] = $this->engineData[ 'lara-access-key-id' ];
+ $newEngineStruct->extra_parameters[ 'Lara-AccessKeySecret' ] = $this->engineData[ 'secret' ];
+ $newEngineStruct->extra_parameters[ 'MMT-License' ] = $this->engineData[ 'mmt-license' ];
+
break;
default:
// MMT
$validEngine = $newEngineStruct = $this->featureSet->filter( 'buildNewEngineStruct', false, (object)[
- 'featureSet' => $this->featureSet,
- 'providerName' => $this->provider,
- 'logged_user' => $this->user,
- 'engineData' => $this->engineData
+ 'featureSet' => $this->featureSet,
+ 'providerName' => $this->provider,
+ 'logged_user' => $this->user,
+ 'engineData' => $this->engineData
] );
break;
@@ -254,14 +272,20 @@ private function add() {
return;
}
- $engineList = $this->featureSet->filter( 'getAvailableEnginesListForUser', Constants_Engines::getAvailableEnginesList(), $this->user );
+ $engineList = Constants_Engines::getAvailableEnginesList();
+ $UserMetadataDao = new MetadataDao();
+ $engineEnabled = $UserMetadataDao->get( $this->user->uid, $newEngineStruct->class_load );
+
+ if ( !empty( $engineEnabled ) ) {
+ unset( $engineList[ $newEngineStruct->class_load ] );
+ }
$engineDAO = new EnginesModel_EngineDAO( Database::obtain() );
$newCreatedDbRowStruct = null;
if ( array_search( $newEngineStruct->class_load, $engineList ) ) {
$newEngineStruct->active = true;
- $newCreatedDbRowStruct = $engineDAO->create( $newEngineStruct );
+ $newCreatedDbRowStruct = $engineDAO->create( $newEngineStruct );
$this->destroyUserEnginesCache();
}
@@ -311,6 +335,26 @@ private function add() {
return;
}
+ } elseif ( $newEngineStruct instanceof LaraStruct ) {
+
+ /**
+ * @var $newTestCreatedMT Lara
+ */
+ $newTestCreatedMT = Engine::createTempInstance( $newCreatedDbRowStruct );
+
+ try {
+ $newTestCreatedMT->getAvailableLanguages();
+ } catch ( LaraException $e ) {
+ $this->result[ 'errors' ][] = $e->getMessage();
+ $engineDAO->delete( $newCreatedDbRowStruct );
+ $this->destroyUserEnginesCache();
+
+ return;
+ }
+
+ $UserMetadataDao = new MetadataDao();
+ $UserMetadataDao->set( $this->user->uid, $newCreatedDbRowStruct->class_load, $newCreatedDbRowStruct->id );
+
} else {
try {
@@ -325,11 +369,12 @@ private function add() {
}
+ $engine_type = explode( "\\", $newCreatedDbRowStruct->class_load );
$this->result[ 'data' ][ 'id' ] = $newCreatedDbRowStruct->id;
$this->result[ 'data' ][ 'name' ] = $newCreatedDbRowStruct->name;
$this->result[ 'data' ][ 'description' ] = $newCreatedDbRowStruct->description;
$this->result[ 'data' ][ 'type' ] = $newCreatedDbRowStruct->type;
- $this->result[ 'data' ][ 'engine_type' ] = $newCreatedDbRowStruct->class_load;
+ $this->result[ 'data' ][ 'engine_type' ] = array_pop( $engine_type );
}
/**
@@ -359,7 +404,12 @@ private function disable() {
return;
}
- $this->featureSet->run( 'postEngineDeletion', $result );
+ $engine = Engine::createTempInstance( $result );
+
+ if ( $engine->isAdaptive() ) {
+ //retrieve OWNER Engine License
+ ( new MetadataDao() )->delete( $this->user->uid, $result->class_load ); // engine_id
+ }
$this->result[ 'data' ][ 'id' ] = $result->id;
diff --git a/lib/Controller/getContributionController.php b/lib/Controller/getContributionController.php
index 89b5d287ed..a80bc6fdaf 100644
--- a/lib/Controller/getContributionController.php
+++ b/lib/Controller/getContributionController.php
@@ -24,27 +24,37 @@ class getContributionController extends ajaxController {
private $__postInput;
private $cross_language;
+ /**
+ * @var ?array
+ */
+ private ?array $context_list_before;
+ /**
+ * @var ?array
+ */
+ private ?array $context_list_after;
public function __construct() {
parent::__construct();
$filterArgs = [
- 'id_segment' => [ 'filter' => FILTER_SANITIZE_NUMBER_INT ],
- 'id_job' => [ 'filter' => FILTER_SANITIZE_NUMBER_INT ],
- 'num_results' => [ 'filter' => FILTER_SANITIZE_NUMBER_INT ],
- 'text' => [ 'filter' => FILTER_UNSAFE_RAW ],
- 'id_translator' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FLAG_STRIP_LOW ],
- 'password' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FLAG_STRIP_LOW ],
- 'current_password' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FLAG_STRIP_LOW ],
- 'is_concordance' => [ 'filter' => FILTER_VALIDATE_BOOLEAN ],
- 'from_target' => [ 'filter' => FILTER_VALIDATE_BOOLEAN ],
- 'context_before' => [ 'filter' => FILTER_UNSAFE_RAW ],
- 'context_after' => [ 'filter' => FILTER_UNSAFE_RAW ],
- 'id_before' => [ 'filter' => FILTER_SANITIZE_NUMBER_INT ],
- 'id_after' => [ 'filter' => FILTER_SANITIZE_NUMBER_INT ],
- 'id_client' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FLAG_STRIP_LOW ],
- 'cross_language' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FORCE_ARRAY ]
+ 'id_segment' => [ 'filter' => FILTER_SANITIZE_NUMBER_INT ],
+ 'id_job' => [ 'filter' => FILTER_SANITIZE_NUMBER_INT ],
+ 'num_results' => [ 'filter' => FILTER_SANITIZE_NUMBER_INT ],
+ 'text' => [ 'filter' => FILTER_UNSAFE_RAW ],
+ 'id_translator' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FLAG_STRIP_LOW ],
+ 'password' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FLAG_STRIP_LOW ],
+ 'current_password' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FLAG_STRIP_LOW ],
+ 'is_concordance' => [ 'filter' => FILTER_VALIDATE_BOOLEAN ],
+ 'from_target' => [ 'filter' => FILTER_VALIDATE_BOOLEAN ],
+ 'context_before' => [ 'filter' => FILTER_UNSAFE_RAW ],
+ 'context_after' => [ 'filter' => FILTER_UNSAFE_RAW ],
+ 'id_before' => [ 'filter' => FILTER_SANITIZE_NUMBER_INT ],
+ 'id_after' => [ 'filter' => FILTER_SANITIZE_NUMBER_INT ],
+ 'id_client' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FLAG_STRIP_LOW ],
+ 'cross_language' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FORCE_ARRAY ],
+ 'context_list_before' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_NO_ENCODE_QUOTES ],
+ 'context_list_after' => [ 'filter' => FILTER_SANITIZE_STRING, 'flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_NO_ENCODE_QUOTES ],
];
$this->__postInput = filter_input_array( INPUT_POST, $filterArgs );
@@ -57,16 +67,18 @@ public function __construct() {
$this->id_before = $this->__postInput[ 'id_before' ];
$this->id_after = $this->__postInput[ 'id_after' ];
- $this->id_job = $this->__postInput[ 'id_job' ];
- $this->num_results = $this->__postInput[ 'num_results' ];
- $this->text = trim( $this->__postInput[ 'text' ] );
- $this->id_translator = $this->__postInput[ 'id_translator' ];
- $this->concordance_search = $this->__postInput[ 'is_concordance' ];
- $this->switch_languages = $this->__postInput[ 'from_target' ];
- $this->password = $this->__postInput[ 'password' ];
- $this->received_password = $this->__postInput[ 'current_password' ];
- $this->id_client = $this->__postInput[ 'id_client' ];
- $this->cross_language = $this->__postInput[ 'cross_language' ];
+ $this->id_job = $this->__postInput[ 'id_job' ];
+ $this->num_results = $this->__postInput[ 'num_results' ];
+ $this->text = trim( $this->__postInput[ 'text' ] );
+ $this->id_translator = $this->__postInput[ 'id_translator' ];
+ $this->concordance_search = $this->__postInput[ 'is_concordance' ];
+ $this->switch_languages = $this->__postInput[ 'from_target' ];
+ $this->password = $this->__postInput[ 'password' ];
+ $this->received_password = $this->__postInput[ 'current_password' ];
+ $this->id_client = $this->__postInput[ 'id_client' ];
+ $this->cross_language = $this->__postInput[ 'cross_language' ];
+ $this->context_list_after = json_decode( $this->__postInput[ 'context_list_after' ], true );
+ $this->context_list_before = json_decode( $this->__postInput[ 'context_list_before' ], true );
if ( $this->id_translator == 'unknown_translator' ) {
$this->id_translator = "";
@@ -119,20 +131,24 @@ public function doAction() {
$this->_getContexts( $jobStruct->source, $jobStruct->target );
}
- $file = (new FilesPartsDao())->getBySegmentId($this->id_segment);
- $owner = (new Users_UserDao())->getProjectOwner( $this->id_job );
-
- $contributionRequest = new ContributionRequestStruct();
- $contributionRequest->id_file = $file->id_file;
- $contributionRequest->id_job = $this->id_job;
- $contributionRequest->password = $this->received_password;
- $contributionRequest->user = $owner;
- $contributionRequest->dataRefMap = $dataRefMap;
- $contributionRequest->contexts = [
- 'context_before' => $this->context_before,
- 'segment' => $this->text,
- 'context_after' => $this->context_after
+ $file = ( new FilesPartsDao() )->getBySegmentId( $this->id_segment );
+ $owner = ( new Users_UserDao() )->getProjectOwner( $this->id_job );
+
+ $contributionRequest = new ContributionRequestStruct();
+ $contributionRequest->id_file = $file->id_file;
+ $contributionRequest->id_job = $this->id_job;
+ $contributionRequest->password = $this->received_password;
+ $contributionRequest->user = $owner;
+ $contributionRequest->dataRefMap = $dataRefMap;
+ $contributionRequest->contexts = [
+ 'context_before' => $this->context_before,
+ 'segment' => $this->text,
+ 'context_after' => $this->context_after
];
+
+ $contributionRequest->context_list_before = $this->context_list_before;
+ $contributionRequest->context_list_after = $this->context_list_after;
+
$contributionRequest->jobStruct = $jobStruct;
$contributionRequest->projectStruct = $projectStruct;
$contributionRequest->segmentId = $this->id_segment;
diff --git a/lib/Controller/loadTMXController.php b/lib/Controller/loadTMXController.php
index 4b038729a6..2affeb325a 100644
--- a/lib/Controller/loadTMXController.php
+++ b/lib/Controller/loadTMXController.php
@@ -126,11 +126,9 @@ public function doAction() {
$fileInfo->name
);
- $this->TMService->addTmxInMyMemory( $file );
+ $this->TMService->addTmxInMyMemory( $file, $this->user );
$uuids[] = [ "uuid" => $file->getUuid(), "name" => $file->getName() ];
- $this->featureSet->run( 'postPushTMX', $file, $this->user );
-
/*
* We update the KeyRing only if this is NOT the Default MyMemory Key
*
diff --git a/lib/Controller/setTranslationController.php b/lib/Controller/setTranslationController.php
index 8d78c6cf48..b48a13fc5b 100644
--- a/lib/Controller/setTranslationController.php
+++ b/lib/Controller/setTranslationController.php
@@ -836,7 +836,7 @@ private function updateJobPEE( array $old_translation, array $new_translation )
'id' => $this->id_job,
'password' => $this->password
] );
- } else {
+ } elseif( $tte != 0 ) {
Jobs_JobDao::updateFields(
[ 'total_time_to_edit' => $tte ],
[
@@ -941,7 +941,6 @@ private function evalSetContribution( $_Translation, $old_translation ) {
Set::contribution( $contributionStruct );
if ( $contributionStruct->id_mt > 1 ) {
- $contributionStruct = $this->featureSet->filter( 'filterSetContributionMT', null, $contributionStruct, $this->project );
Set::contributionMT( $contributionStruct );
}
diff --git a/lib/Model/EnginesModel/EngineStruct.php b/lib/Model/EnginesModel/EngineStruct.php
index 378a3723ad..3e486fc313 100644
--- a/lib/Model/EnginesModel/EngineStruct.php
+++ b/lib/Model/EnginesModel/EngineStruct.php
@@ -69,7 +69,7 @@ class EnginesModel_EngineStruct
/**
- * @var array
+ * @var array|string
*/
public $extra_parameters;
@@ -186,7 +186,7 @@ public function getExtraParamsAsArray() {
return $this->extra_parameters;
}
- if ( empty( $this->extra_parameters ) or $this->extra_parameters === null ) {
+ if ( empty( $this->extra_parameters ) ) {
return [];
}
diff --git a/lib/Model/EnginesModel/LaraStruct.php b/lib/Model/EnginesModel/LaraStruct.php
new file mode 100644
index 0000000000..f3a7d495ce
--- /dev/null
+++ b/lib/Model/EnginesModel/LaraStruct.php
@@ -0,0 +1,93 @@
+ "memories/content",
+ "user_update_activate" => "memories/connect",
+ ];
+
+ /**
+ * @var string
+ */
+ public $class_load = Lara::class;
+
+
+ /**
+ * @var array
+ */
+ public $extra_parameters = [
+ 'Lara-AccessKeyId' => "",
+ 'Lara-AccessKeySecret' => "",
+ 'MMT-License' => ""
+ ];
+
+ /**
+ * @var int
+ */
+ public $google_api_compliant_version = 2;
+
+ /**
+ * @var int
+ */
+ public $penalty = 14;
+
+ /**
+ * An empty struct
+ * @return LaraStruct
+ */
+ public static function getStruct(): LaraStruct {
+ return new LaraStruct();
+ }
+}
\ No newline at end of file
diff --git a/lib/Model/Users/MetadataDao.php b/lib/Model/Users/MetadataDao.php
index 317941c612..678a5aa1ce 100644
--- a/lib/Model/Users/MetadataDao.php
+++ b/lib/Model/Users/MetadataDao.php
@@ -4,6 +4,7 @@
use Database;
use PDO;
+use ReflectionException;
class MetadataDao extends \DataAccess_AbstractDao {
@@ -57,15 +58,16 @@ public function getAllByUid( $uid ) {
* @param $key
*
* @return MetadataStruct
+ * @throws ReflectionException
*/
- public function get( $uid, $key ) {
+ public function get( $uid, $key ): ?MetadataStruct {
$stmt = $this->_getStatementForQuery( self::_query_metadata_by_uid_key );
+ /** @var $result MetadataStruct */
$result = $this->_fetchObject( $stmt, new MetadataStruct(), [
'uid' => $uid,
'key' => $key
] );
-
- return @$result[ 0 ];
+ return $result[ 0 ] ?? null;
}
public function destroyCacheKey( $uid, $key ){
diff --git a/lib/Plugins/Features/Mmt.php b/lib/Plugins/Features/Mmt.php
index 1863d0b00d..4844a6ae8f 100644
--- a/lib/Plugins/Features/Mmt.php
+++ b/lib/Plugins/Features/Mmt.php
@@ -61,36 +61,6 @@ public static function bootstrapCompleted() {
Constants_Engines::setInEnginesList( Constants_Engines::MMT );
}
- /**
- * Called in @param $enginesList
- *
- * @param Users_UserStruct $userStruct
- *
- * @return mixed
- * @throws Exception
- * @see engineController::add()
- *
- * Only one MMT engine per user can be registered
- *
- */
- public static function getAvailableEnginesListForUser( $enginesList, Users_UserStruct $userStruct ) {
-
- $UserMetadataDao = new MetadataDao();
- $engineEnabled = $UserMetadataDao->get( $userStruct->uid, self::FEATURE_CODE );
-
- if ( !empty( $engineEnabled ) ) {
-
- $engine = Engine::getInstance($engineEnabled->value);
- $engineRecord = $engine->getEngineRecord();
-
- if($engineRecord->active == 1){
- unset( $enginesList[ Constants_Engines::MMT ] ); // remove the engine from the list of available engines like it was disabled, so it will not be created
- }
- }
-
- return $enginesList;
- }
-
/**
* Called in @param EnginesModel_EngineStruct $newCreatedDbRowStruct
*
@@ -110,28 +80,28 @@ public static function postEngineCreation( EnginesModel_EngineStruct $newCreated
/** @var Engines_MMT $newTestCreatedMT */
try {
$newTestCreatedMT = Engine::createTempInstance( $newCreatedDbRowStruct );
- } catch (Exception $exception){
- throw new Exception("MMT license not valid");
+ } catch ( Exception $exception ) {
+ throw new Exception( "MMT license not valid" );
}
// Check account
try {
$checkAccount = $newTestCreatedMT->checkAccount();
- if(!isset($checkAccount['billingPeriod']['planForCatTool'])){
- throw new Exception("MMT license not valid");
+ if ( !isset( $checkAccount[ 'billingPeriod' ][ 'planForCatTool' ] ) ) {
+ throw new Exception( "MMT license not valid" );
}
- $planForCatTool = $checkAccount['billingPeriod']['planForCatTool'];
+ $planForCatTool = $checkAccount[ 'billingPeriod' ][ 'planForCatTool' ];
- if($planForCatTool === false){
- throw new Exception("The ModernMT license you entered cannot be used inside CAT tools. Please subscribe to a suitable license to start using the ModernMT plugin.");
+ if ( $planForCatTool === false ) {
+ throw new Exception( "The ModernMT license you entered cannot be used inside CAT tools. Please subscribe to a suitable license to start using the ModernMT plugin." );
}
- } catch ( Exception $e ){
+ } catch ( Exception $e ) {
( new EnginesModel_EngineDAO( Database::obtain() ) )->delete( $newCreatedDbRowStruct );
- throw new Exception($e->getMessage(), $e->getCode());
+ throw new Exception( $e->getMessage(), $e->getCode() );
}
try {
@@ -173,31 +143,13 @@ public function engineCreationFailed( $errorObject, $class_load ) {
}
/**
- * Called in @param EnginesModel_EngineStruct $engineStruct
- * @throws Exception
- * @see engineController::disable()
- */
- public static function postEngineDeletion( EnginesModel_EngineStruct $engineStruct ) {
-
- $UserMetadataDao = new MetadataDao();
- $engineEnabled = $UserMetadataDao->setCacheTTL( 60 * 60 * 24 * 30 )->get( $engineStruct->uid, self::FEATURE_CODE );
-
- if ( $engineStruct->class_load == Constants_Engines::MMT ) {
-
- if ( !empty( $engineEnabled ) && $engineEnabled->value == $engineStruct->id /* redundant */ ) {
- $UserMetadataDao->delete( $engineStruct->uid, self::FEATURE_CODE ); // delete the engine from user
- }
-
- }
- }
-
- /**
- * Called in @param $config
+ * Called in
*
+ * @param array $config
* @param Engines_AbstractEngine $engine
* @param Jobs_JobStruct $jobStruct
*
- * @return mixed
+ * @return array
* @throws Exception
* @see getContributionController::doAction()
*
@@ -243,13 +195,13 @@ public static function analysisBeforeMTGetContribution( $config, Engines_Abstrac
$config[ 'mt_context' ] = $mt_context->value;
}
- if( $mt_evaluation ){
+ if ( $mt_evaluation ) {
$config[ 'include_score' ] = true;
}
$config[ 'secret_key' ] = self::getG2FallbackSecretKey();
$config[ 'priority' ] = 'background';
- $config[ 'keys' ] = @$config[ 'id_user' ];
+ $config[ 'keys' ] = $config[ 'id_user' ] ?? [];
}
@@ -319,12 +271,12 @@ public function filterCreateProjectFeatures( $projectFeatures, $controller ) {
if ( $engine instanceof Engines_MMT ) {
/**
* @var $availableLangs
- *
- * {
+ *
*/
$availableLangs = $engine->getAvailableLanguages();
$target_language_list = explode( ",", $controller->postInput[ 'target_lang' ] );
@@ -479,110 +431,6 @@ public static function beforeSendSegmentsToTheQueue( array $segments, array $pro
}
- /**
- *
- * Called in @param $response
- *
- * @param ContributionSetStruct $contributionStruct
- * @param Projects_ProjectStruct $projectStruct
- *
- * @return ContributionSetStruct|null
- * @see \setTranslationController::evalSetContribution()
- *
- */
- public function filterSetContributionMT( $response, ContributionSetStruct $contributionStruct, Projects_ProjectStruct $projectStruct ) {
-
- /**
- * When a project is created, it's features and used plugins are stored in project_metadata,
- * When MMT is disabled at global level, old projects will have this feature enabled in meta_data, but the plugin is not Bootstrapped with the hook @see Mmt::bootstrapCompleted()
- *
- * So, the MMT engine is not in the list of available plugins, check and exclude if the Plugin is not enables at global level
- */
- if ( !array_key_exists( Constants_Engines::MMT, Constants_Engines::getAvailableEnginesList() ) ) {
- return $response;
- }
-
- //Project is not anonymous
- if ( !$projectStruct->isAnonymous() ) {
-
- try {
-
- $features = FeatureSet::splitString( $projectStruct->getMetadataValue( Projects_MetadataDao::FEATURES_KEY ) );
-
- if ( in_array( self::FEATURE_CODE, $features ) ) {
- $response = $contributionStruct;
- } else {
- $response = null;
- }
-
- } catch ( Exception $e ) {
- //DO Nothing
- }
-
- }
-
- return $response;
-
- }
-
- /**
- *
- * @param TMSFile $file
- * @param $user
- *
- * Called in @see \ProjectManager::_pushTMXToMyMemory()
- * Called in @see \loadTMXController::doAction()
- *
- */
- public function postPushTMX( TMSFile $file, $user ) {
-
- //Project is not anonymous
- if ( !empty( $user ) ) {
-
- $uStruct = $user;
- if ( !$uStruct instanceof Users_UserStruct ) {
- $uStruct = ( new Users_UserDao() )->setCacheTTL( 60 * 60 * 24 * 30 )->getByEmail( $user );
- }
-
- //retrieve OWNER MMT License
- $ownerMmtEngineMetaData = ( new MetadataDao() )->setCacheTTL( 60 * 60 * 24 * 30 )->get( $uStruct->uid, self::FEATURE_CODE ); // engine_id
- try {
-
- if ( !empty( $ownerMmtEngineMetaData ) ) {
-
- /**
- * @var Engines_MMT $MMTEngine
- */
- $MMTEngine = Engine::getInstance( $ownerMmtEngineMetaData->value );
-
- //
- // ==============================================
- // Call MMT only if the tmx is already imported
- // over an existing key in MMT
- // ==============================================
- //
-
- $associatedMemories = $MMTEngine->getAllMemories();
- foreach ( $associatedMemories as $memory ) {
-
- if ( 'x_mm-' . trim( $file->getTmKey() ) === $memory[ 'externalId' ] ) {
- $fileName = AbstractFilesStorage::pathinfo_fix( $file->getFilePath(), PATHINFO_FILENAME );
- $result = $MMTEngine->import( $file->getFilePath(), $file->getTmKey(), $fileName );
-
- if ( $result->responseStatus >= 400 ) {
- throw new Exception( $result->error->message );
- }
- }
- }
- }
-
- } catch ( Exception $e ) {
- Log::doJsonLog( $e->getMessage() );
- }
- }
-
- }
-
/**
* Called in @param $isValid
*
diff --git a/lib/Utils/Analysis/Workers/TMAnalysisWorker.php b/lib/Utils/Analysis/Workers/TMAnalysisWorker.php
index e32ef0e3f6..72a0b38fe2 100644
--- a/lib/Utils/Analysis/Workers/TMAnalysisWorker.php
+++ b/lib/Utils/Analysis/Workers/TMAnalysisWorker.php
@@ -274,7 +274,7 @@ protected function _updateRecord( QueueElement $queueElement ) {
$this->_incrementAnalyzedCount( $queueElement->params->pid, $eq_words, $standard_words );
$this->_decSegmentsToAnalyzeOfWaitingProjects( $queueElement->params->pid );
$this->_tryToCloseProject( $queueElement->params );
-
+
}
/**
@@ -640,6 +640,9 @@ protected function _getMT( Engines_AbstractEngine $mtEngine, $_config, QueueElem
$config = $mtEngine->getConfigStruct();
$config = array_merge( $config, $_config );
+ // set for lara engine in case, this is needed to catch all owner keys
+ $config[ 'all_job_tm_keys' ] = $queueElement->params->tm_keys;
+
//if a callback is not set only the first argument is returned, get the config params from the callback
$config = $this->featureSet->filter( 'analysisBeforeMTGetContribution', $config, $mtEngine, $queueElement, $mt_evaluation );
diff --git a/lib/Utils/AsyncTasks/Workers/GetContributionWorker.php b/lib/Utils/AsyncTasks/Workers/GetContributionWorker.php
index 069f9c38b8..9a524ea697 100644
--- a/lib/Utils/AsyncTasks/Workers/GetContributionWorker.php
+++ b/lib/Utils/AsyncTasks/Workers/GetContributionWorker.php
@@ -9,12 +9,15 @@
namespace AsyncTasks\Workers;
+use API\Commons\Exceptions\AuthenticationError;
use Constants\Ices;
use Constants_TranslationStatus;
use Contribution\ContributionRequestStruct;
use Engines_DeepL;
use Engines_MMT;
use Exception;
+use Exceptions\NotFoundException;
+use Exceptions\ValidationError;
use FeatureSet;
use INIT;
use Jobs\MetadataDao;
@@ -28,6 +31,7 @@
use TaskRunner\Commons\AbstractWorker;
use TaskRunner\Commons\QueueElement;
use TaskRunner\Exceptions\EndQueueException;
+use TaskRunner\Exceptions\ReQueueException;
use TmKeyManagement_TmKeyManagement;
use Translations_SegmentTranslationDao;
use Users_UserStruct;
@@ -188,7 +192,7 @@ protected function _publishPayload( array $content, ContributionRequestStruct $c
protected function _extractAvailableKeysForUser( ContributionRequestStruct $contributionStruct ) {
//find all the job's TMs with write grants and make a contribution to them
- $tm_keys = TmKeyManagement_TmKeyManagement::getJobTmKeys( $contributionStruct->getJobStruct()->tm_keys, 'r', 'tm', $contributionStruct->user->uid, $contributionStruct->userRole );
+ $tm_keys = TmKeyManagement_TmKeyManagement::getJobTmKeys( $contributionStruct->getJobStruct()->tm_keys, 'r', 'tm', $contributionStruct->getUser()->uid, $contributionStruct->userRole );
$keyList = [];
if ( !empty( $tm_keys ) ) {
@@ -396,20 +400,22 @@ protected function tokenizeSourceSearch( $text ) {
/**
* @param ContributionRequestStruct $contributionStruct
* @param Jobs_JobStruct $jobStruct
- * @param $targetLang
- * @param $featureSet
+ * @param string $targetLang
+ * @param FeatureSet $featureSet
* @param bool $isCrossLang
*
* @return array
+ * @throws EndQueueException
+ * @throws ReQueueException
* @throws Exception
*/
- protected function _getMatches( ContributionRequestStruct $contributionStruct, $jobStruct, $targetLang, $featureSet, $isCrossLang = false ) {
+ protected function _getMatches( ContributionRequestStruct $contributionStruct, Jobs_JobStruct $jobStruct, string $targetLang, FeatureSet $featureSet, bool $isCrossLang = false ): array {
$_config = [];
$_config[ 'segment' ] = $contributionStruct->getContexts()->segment;
$_config[ 'source' ] = $jobStruct->source;
$_config[ 'target' ] = $targetLang;
- $_config[ 'uid' ] = ( $contributionStruct->user !== null ? $contributionStruct->user->uid : 0 );
+ $_config[ 'uid' ] = $contributionStruct->getUser()->uid ?? 0;
$_config[ 'email' ] = INIT::$MYMEMORY_API_KEY;
@@ -500,7 +506,11 @@ protected function _getMatches( ContributionRequestStruct $contributionStruct, $
$mt_result = [];
- if ( $jobStruct->id_mt_engine > 1 /* Request MT Directly */ && !$contributionStruct->concordanceSearch ) {
+ if (
+ $jobStruct->id_mt_engine > 1 /* Request MT Directly */ &&
+ !$contributionStruct->concordanceSearch &&
+ !$isCrossLang
+ ) {
if ( empty( $tms_match ) || (int)str_replace( "%", "", $tms_match[ 0 ][ 'match' ] ) < 100 ) {
@@ -510,51 +520,18 @@ protected function _getMatches( ContributionRequestStruct $contributionStruct, $
//if a callback is not set only the first argument is returned, get the config params from the callback
$config = $featureSet->filter( 'beforeGetContribution', $config, $mt_engine, $jobStruct );
- $config[ 'segment' ] = $contributionStruct->getContexts()->segment;
- $config[ 'source' ] = $jobStruct->source;
- $config[ 'target' ] = $jobStruct->target;
- $config[ 'email' ] = INIT::$MYMEMORY_API_KEY;
- $config[ 'segid' ] = $contributionStruct->segmentId;
- $config[ 'job_id' ] = $jobStruct->id;
- $config[ 'job_password' ] = $jobStruct->password;
- $config[ 'session' ] = $contributionStruct->getSessionId();
-
- if ( $mt_engine instanceof Engines_MMT ) {
- $metadataDao = new Projects_MetadataDao();
- $metadata = $metadataDao->setCacheTTL( 86400 )->get( $contributionStruct->getProjectStruct()->id, 'mmt_glossaries' );
-
- if ( $metadata !== null ) {
- $metadata = html_entity_decode( $metadata->value );
- $mmtGlossariesArray = json_decode( $metadata, true );
-
- $config[ 'glossaries' ] = implode( ",", $mmtGlossariesArray[ 'glossaries' ] );
- $config[ 'ignore_glossary_case' ] = $mmtGlossariesArray[ 'ignore_glossary_case' ];
- }
- }
-
- // glossaries (only for DeepL)
- if ( $mt_engine instanceof Engines_DeepL ) {
-
- $extraParams = $mt_engine->getEngineRecord()->extra_parameters;
-
- if ( !isset( $extraParams[ 'DeepL-Auth-Key' ] ) ) {
- throw new Exception( "DeepL API key not set" );
- }
-
- $metadataDao = new Projects_MetadataDao();
- $deepLFormality = $metadataDao->get( $contributionStruct->getProjectStruct()->id, 'deepl_formality', 86400 );
- $deepLIdGlossary = $metadataDao->get( $contributionStruct->getProjectStruct()->id, 'deepl_id_glossary', 86400 );
-
- if ( $deepLFormality !== null ) {
- $config[ 'formality' ] = $deepLFormality->value;
- }
-
- if ( $deepLIdGlossary !== null ) {
- $config[ 'idGlossary' ] = $deepLIdGlossary->value;
- }
-
- $mt_engine->setApiKey( $extraParams[ 'DeepL-Auth-Key' ] );
- }
+ $config[ 'segment' ] = $contributionStruct->getContexts()->segment;
+ $config[ 'source' ] = $jobStruct->source;
+ $config[ 'target' ] = $jobStruct->target;
+ $config[ 'email' ] = INIT::$MYMEMORY_API_KEY;
+ $config[ 'segid' ] = $contributionStruct->segmentId;
+ $config[ 'job_id' ] = $jobStruct->id;
+ $config[ 'job_password' ] = $jobStruct->password;
+ $config[ 'session' ] = $contributionStruct->getSessionId();
+ $config[ 'all_job_tm_keys' ] = $jobStruct->tm_keys;
+ $config[ 'project_id' ] = $contributionStruct->getProjectStruct()->id;
+ $config[ 'context_list_before' ] = $contributionStruct->context_list_before;
+ $config[ 'context_list_after' ] = $contributionStruct->context_list_after;
$mt_result = $mt_engine->get( $config );
}
diff --git a/lib/Utils/AsyncTasks/Workers/SetContributionMTWorker.php b/lib/Utils/AsyncTasks/Workers/SetContributionMTWorker.php
index 10b23c585f..a3ac26a371 100644
--- a/lib/Utils/AsyncTasks/Workers/SetContributionMTWorker.php
+++ b/lib/Utils/AsyncTasks/Workers/SetContributionMTWorker.php
@@ -51,7 +51,7 @@ protected function _set( array $config, ContributionSetStruct $contributionStruc
$config[ 'translation' ] = $contributionStruct->translation;
$config[ 'session' ] = $contributionStruct->getSessionId();
$config[ 'uid' ] = $contributionStruct->uid;
- $config[ 'set_mt' ] = ( $jobStruct->id_mt_engine != 1 ) ? false : true;
+ $config[ 'set_mt' ] = $jobStruct->id_mt_engine == 1; // negate, if mt is 1, then is mymemory, and the flag set_mt must be set to true
// set the contribution for every key in the job belonging to the user
$res = $this->_engine->set( $config );
@@ -70,11 +70,13 @@ protected function _set( array $config, ContributionSetStruct $contributionStruc
*/
protected function _update( array $config, ContributionSetStruct $contributionStruct, $id_mt_engine = 0 ) {
- $config[ 'segment' ] = $contributionStruct->segment;
- $config[ 'translation' ] = $contributionStruct->translation;
- $config[ 'tuid' ] = $contributionStruct->id_job . ":" . $contributionStruct->id_segment;
- $config[ 'session' ] = $contributionStruct->getSessionId();
- $config[ 'set_mt' ] = ( $id_mt_engine != 1 ) ? false : true;
+ $config[ 'segment' ] = $contributionStruct->segment;
+ $config[ 'translation' ] = $contributionStruct->translation;
+ $config[ 'tuid' ] = $contributionStruct->id_job . ":" . $contributionStruct->id_segment;
+ $config[ 'session' ] = $contributionStruct->getSessionId();
+ $config[ 'set_mt' ] = $id_mt_engine == 1; // negate, if mt is 1, then is mymemory, and the flag set_mt must be set to true
+ $config[ 'context_before' ] = $contributionStruct->context_before;
+ $config[ 'context_after' ] = $contributionStruct->context_after;
// set the contribution for every key in the job belonging to the user
$res = $this->_engine->update( $config );
diff --git a/lib/Utils/AsyncTasks/Workers/SetContributionWorker.php b/lib/Utils/AsyncTasks/Workers/SetContributionWorker.php
index 92a3ba4ba2..3aeeb2af82 100644
--- a/lib/Utils/AsyncTasks/Workers/SetContributionWorker.php
+++ b/lib/Utils/AsyncTasks/Workers/SetContributionWorker.php
@@ -83,6 +83,13 @@ protected function _execContribution( ContributionSetStruct $contributionStruct
$this->_loadEngine( $jobStruct );
+ /**
+ * @see Engines_AbstractEngine::$_isAdaptive
+ */
+ if( !$this->_engine->isAdaptive() ){
+ return;
+ }
+
$config = $this->_engine->getConfigStruct();
$config[ 'source' ] = $jobStruct->source;
$config[ 'target' ] = $jobStruct->target;
diff --git a/lib/Utils/Constants/Engines.php b/lib/Utils/Constants/Engines.php
index 3a1850bd48..7a4fe9979b 100644
--- a/lib/Utils/Constants/Engines.php
+++ b/lib/Utils/Constants/Engines.php
@@ -1,5 +1,7 @@
self::INTENTO,
self::MMT => self::MMT,
self::DEEPL => self::DEEPL,
+ Lara::class => Lara::class, // new namespaced engine classes must be loaded by fully qualified class name
];
/**
diff --git a/lib/Utils/Contribution/ContributionRequestStruct.php b/lib/Utils/Contribution/ContributionRequestStruct.php
index 4f7218dd4a..5b61bc7e31 100644
--- a/lib/Utils/Contribution/ContributionRequestStruct.php
+++ b/lib/Utils/Contribution/ContributionRequestStruct.php
@@ -34,6 +34,9 @@ class ContributionRequestStruct extends ShapelessConcreteStruct implements DataA
'context_after' => null
];
+ public ?array $context_list_before = null;
+ public ?array $context_list_after = null;
+
/**
* @var string
*/
diff --git a/lib/Utils/Engine.php b/lib/Utils/Engine.php
index 679f520c7a..5bf36503c7 100644
--- a/lib/Utils/Engine.php
+++ b/lib/Utils/Engine.php
@@ -37,8 +37,11 @@ public static function getInstance( $id ) {
}
$className = 'Engines_' . $engineRecord->class_load;
- if ( !class_exists( $className, true ) ) {
- throw new Exception( "Engine Class $className not Found" );
+ if ( !class_exists( $className ) ) {
+ $className = $engineRecord->class_load;
+ if( !class_exists( $className ) ){
+ throw new Exception( "Engine Class $className not Found" );
+ }
}
return new $className( $engineRecord );
@@ -48,10 +51,18 @@ public static function getInstance( $id ) {
/**
* @param EnginesModel_EngineStruct $engineRecord
*
- * @return mixed
+ * @return Engines_EngineInterface
+ * @throws Exception
*/
- public static function createTempInstance( EnginesModel_EngineStruct $engineRecord ) {
+ public static function createTempInstance( EnginesModel_EngineStruct $engineRecord ): Engines_EngineInterface {
+
$className = 'Engines_' . $engineRecord->class_load;
+ if ( !class_exists( $className ) ) {
+ $className = $engineRecord->class_load;
+ if( !class_exists( $className ) ){
+ throw new Exception( "Engine Class $className not Found" );
+ }
+ }
return new $className( $engineRecord );
}
diff --git a/lib/Utils/Engines/AbstractEngine.php b/lib/Utils/Engines/AbstractEngine.php
index 945ac59700..35b5928f9b 100644
--- a/lib/Utils/Engines/AbstractEngine.php
+++ b/lib/Utils/Engines/AbstractEngine.php
@@ -26,6 +26,11 @@ abstract class Engines_AbstractEngine implements Engines_EngineInterface {
protected $_isAnalysis = false;
protected $_skipAnalysis = false;
+ /**
+ * @var bool True if the engine can receive contributions through a `set/update` method.
+ */
+ protected bool $_isAdaptive = false;
+
/**
* @var bool
*/
@@ -204,7 +209,6 @@ public function call( $function, array $parameters = [], $isPostRequest = false,
$this->error = []; // reset last error
if ( !$this->$function ) {
- //Log::doJsonLog( 'Requested method ' . $function . ' not Found.' );
$this->result = [
'error' => [
'code' => -43,
@@ -283,6 +287,10 @@ public function getEngineRow() {
return clone $this->engineRecord;
}
+ public function isAdaptive(): bool {
+ return $this->_isAdaptive;
+ }
+
/**
* This function is PHP7 compatible
*
@@ -334,4 +342,9 @@ protected function GoogleTranslateFallback( $_config ) {
return $gtEngine->get( $_config );
}
+
+ public function importMemory( string $filePath, string $memoryKey, Users_UserStruct $user ){
+
+ }
+
}
diff --git a/lib/Utils/Engines/DeepL.php b/lib/Utils/Engines/DeepL.php
index 4713addbb9..516f38151c 100644
--- a/lib/Utils/Engines/DeepL.php
+++ b/lib/Utils/Engines/DeepL.php
@@ -53,6 +53,26 @@ public function get( $_config ) {
$source = explode( "-", $_config[ 'source' ] );
$target = explode( "-", $_config[ 'target' ] );
+ $extraParams = $this->getEngineRecord()->extra_parameters;
+
+ if ( !isset( $extraParams[ 'DeepL-Auth-Key' ] ) ) {
+ throw new Exception( "DeepL API key not set" );
+ }
+
+ // glossaries (only for DeepL)
+ $metadataDao = new Projects_MetadataDao();
+ $deepLFormality = $metadataDao->get( $_config[ 'project_id' ], 'deepl_formality', 86400 );
+ $deepLIdGlossary = $metadataDao->get( $_config[ 'project_id' ], 'deepl_id_glossary', 86400 );
+
+ if ( $deepLFormality !== null ) {
+ $_config[ 'formality' ] = $deepLFormality->value;
+ }
+
+ if ( $deepLIdGlossary !== null ) {
+ $_config[ 'idGlossary' ] = $deepLIdGlossary->value;
+ }
+ // glossaries (only for DeepL)
+
$parameters = [
'text' => [
$_config['segment'],
@@ -64,7 +84,7 @@ public function get( $_config ) {
];
$headers = [
- 'Authorization: DeepL-Auth-Key ' . $this->apiKey,
+ 'Authorization: DeepL-Auth-Key ' . $extraParams[ 'DeepL-Auth-Key' ],
'Content-Type: application/json'
];
diff --git a/lib/Utils/Engines/EngineInterface.php b/lib/Utils/Engines/EngineInterface.php
index 4da2db2955..74d6fbe19c 100644
--- a/lib/Utils/Engines/EngineInterface.php
+++ b/lib/Utils/Engines/EngineInterface.php
@@ -52,4 +52,14 @@ public function setAnalysis();
*/
public function getEngineRow();
+ /**
+ * @return bool
+ */
+ public function isAdaptive(): bool;
+
+ /**
+ * @return mixed
+ */
+ public function importMemory( string $filePath, string $memoryKey, Users_UserStruct $user );
+
}
\ No newline at end of file
diff --git a/lib/Utils/Engines/Lara.php b/lib/Utils/Engines/Lara.php
new file mode 100644
index 0000000000..3740592588
--- /dev/null
+++ b/lib/Utils/Engines/Lara.php
@@ -0,0 +1,363 @@
+engineRecord->type != "MT" ) {
+ throw new Exception( "Engine {$this->engineRecord->id} is not a MT engine, found {$this->engineRecord->type} -> {$this->engineRecord->class_load}" );
+ }
+
+ $this->_skipAnalysis = true;
+
+ }
+
+ /**
+ * Get MMTServiceApi client
+ *
+ * @return Translator
+ * @throws Exception
+ */
+ protected function _getClient(): Translator {
+
+ if ( !empty( $this->clientLoaded ) ) {
+ return $this->clientLoaded;
+ }
+
+ $extraParams = $this->engineRecord->getExtraParamsAsArray();
+ $credentials = new LaraCredentials( $extraParams[ 'Lara-AccessKeyId' ], $extraParams[ 'Lara-AccessKeySecret' ] );
+
+ $mmtStruct = EnginesModel_MMTStruct::getStruct();
+ $mmtStruct->type = Constants_Engines::MT;
+ $mmtStruct->extra_parameters = [
+ 'MMT-License' => $extraParams[ 'MMT-License' ] ?: INIT::$DEFAULT_MMT_KEY,
+ 'MMT-pretranslate' => true,
+ 'MMT-preimport' => false,
+ ];
+
+ $this->mmtUserFallback = Engine::createTempInstance( $mmtStruct );
+
+ $this->clientLoaded = new Translator( $credentials );
+
+ return $this->clientLoaded;
+ }
+
+ /**
+ * Get the available languages in MMT
+ *
+ * @return array
+ * @throws LaraException
+ * @throws ReflectionException
+ * @throws Exception
+ */
+ public function getAvailableLanguages(): array {
+
+ $cache = ( new RedisHandler() )->getConnection();
+
+ $value = [];
+
+ try {
+ $value = unserialize( $cache->get( "lara_languages" ) );
+ } catch ( Throwable $e ) {
+ }
+
+ if ( !empty( $value ) ) {
+ return $value;
+ }
+
+ $client = $this->_getClient();
+ $value = $client->getLanguages();
+ $cache->setex( "lara_languages", 86400, serialize( $value ) );
+
+ return $value;
+
+ }
+
+ protected function _decode( $rawValue, array $parameters = [], $function = null ) {
+ // Not used since Lara works with an external client (through composer)
+ }
+
+ /**
+ * @inheritDoc
+ * @throws LaraException
+ * @throws ReflectionException
+ * @throws Exception
+ */
+ public function get( $_config ) {
+
+ $tm_keys = TmKeyManagement_TmKeyManagement::getOwnerKeys( [ $_config[ 'all_job_tm_keys' ] ], 'r' );
+ $_config[ 'keys' ] = array_map( function ( $tm_key ) {
+ /**
+ * @var $tm_key TmKeyManagement_MemoryKeyStruct
+ */
+ return $tm_key->key;
+ }, $tm_keys );
+
+
+ // init lara client and mmt fallback
+ $client = $this->_getClient();
+
+ // configuration for mmt fallback
+ $_config[ 'secret_key' ] = Mmt::getG2FallbackSecretKey();
+ if ( $this->_isAnalysis && $this->_skipAnalysis ) {
+ // for MMT
+ $_config[ 'include_score' ] = true;
+ $_config[ 'priority' ] = 'background';
+
+ // analysis on Lara is disabled, fallback on MMT
+
+ return $this->mmtUserFallback->get( $_config );
+ } else {
+ $_config[ 'priority' ] = 'normal';
+ }
+
+ $_lara_keys = $this->_reMapKeyList( $_config[ 'keys' ] );
+
+ $languagesList = $this->getAvailableLanguages();
+
+ if ( in_array( $_config[ 'source' ], $languagesList ) && in_array( $_config[ 'target' ], $languagesList ) ) {
+ // call lara
+ $translateOptions = new TranslateOptions();
+ $translateOptions->setAdaptTo( $_lara_keys );
+ $translateOptions->setPriority( $_config[ 'priority' ] );
+ $translateOptions->setMultiline( true );
+
+ $request_translation = [];
+
+ foreach ( $_config[ 'context_list_before' ] as $c ) {
+ $request_translation[] = new TextBlock( $c, false );
+ }
+
+ $request_translation[] = new TextBlock( $_config[ 'segment' ] );
+
+ foreach ( $_config[ 'context_list_after' ] as $c ) {
+ $request_translation[] = new TextBlock( $c, false );
+ }
+
+ $time_start = microtime( true );
+ $translationResponse = $client->translate( $request_translation, $_config[ 'source' ], $_config[ 'target' ], $translateOptions );
+ $time_end = microtime( true );
+ $time = $time_end - $time_start;
+
+ Log::doJsonLog( [
+ 'LARA REQUEST' => 'GET https://api.laratranslate.com/translate',
+ 'timing' => [ 'Total Time' => $time, 'Request Start Time' => $time_start, 'Request End Time' => $time_end ],
+ 'q' => $request_translation,
+ 'adapt_to' => $_lara_keys,
+ 'source' => $_config[ 'source' ],
+ 'target' => $_config[ 'target' ],
+ 'priority' => $_config[ 'priority' ],
+ 'multiline' => true,
+ ] );
+
+ $translation = "";
+ $tList = $translationResponse->getTranslation();
+ foreach ( $tList as $t ) {
+ if ( $t->isTranslatable() ) {
+ $translation = $t->getText();
+ break;
+ }
+ }
+
+ } else {
+ // mmt fallback
+ return $this->mmtUserFallback->get( $_config );
+ }
+
+ return ( new Engines_Results_MyMemory_Matches(
+ $_config[ 'segment' ],
+ $translation,
+ 100 - $this->getPenalty() . "%",
+ "MT-" . $this->getName(),
+ date( "Y-m-d" )
+ ) )->getMatches( 1, [], $_config[ 'source' ], $_config[ 'target' ] );
+
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function set( $_config ) {
+ // TODO: Implement set() method.
+ }
+
+ /**
+ * @inheritDoc
+ * @throws Exception
+ */
+ public function update( $_config ) {
+
+ $client = $this->_getClient();
+ $_keys = $this->_reMapKeyList( $_config[ 'keys' ] ?? [] );
+ try {
+
+ $time_start = microtime( true );
+ // call lara
+ $client->memories->addTranslation(
+ $_keys,
+ $_config[ 'source' ],
+ $_config[ 'target' ],
+ $_config[ 'segment' ],
+ $_config[ 'translation' ],
+ $_config[ 'tuid' ],
+ $_config[ 'context_before' ],
+ $_config[ 'context_after' ],
+ );
+ $time_end = microtime( true );
+ $time = $time_end - $time_start;
+
+ Log::doJsonLog( [
+ 'LARA REQUEST' => 'PUT https://api.laratranslate.com/memories/content',
+ 'timing' => [ 'Total Time' => $time, 'Request Start Time' => $time_start, 'Request End Time' => $time_end ],
+ 'keys' => $_keys,
+ 'source' => $_config[ 'source' ],
+ 'target' => $_config[ 'target' ],
+ 'sentence' => $_config[ 'segment' ],
+ 'translation' => $_config[ 'translation' ],
+ 'tuid' => $_config[ 'tuid' ],
+ 'sentence_before' => $_config[ 'context_before' ],
+ 'sentence_after' => $_config[ 'context_after' ],
+ ] );
+
+ } catch ( LaraApiException $e ) {
+ // Lara license expired/changed (401) or account deleted (403)
+ Log::doJsonLog( $e->getMessage() );
+
+ // DO NOT REQUEUE FOR LARA FAILURE ONLY
+
+ } catch ( Exception $e ) {
+ // for any other exception (HTTP connection or timeout) requeue
+ return false;
+ }
+
+ // let MMT to have the last word on requeue
+ return $this->mmtUserFallback->update( $_config );
+
+ }
+
+ /**
+ * @throws LaraException
+ */
+ public function importMemory( string $filePath, string $memoryKey, Users_UserStruct $user ) {
+
+ $clientMemories = $this->_getClient()->memories;
+ $associatedMemories = $clientMemories->getAll();
+ $memoryFound = false;
+
+ foreach ( $associatedMemories as $memory ) {
+ if ( 'ext_my_' . trim( $memoryKey ) === $memory->getExternalId() ) {
+ $memoryFound = true;
+ break;
+ }
+ }
+
+ if ( !$memoryFound ) {
+ return null;
+ }
+
+ $fp_out = gzopen( "$filePath.gz", 'wb9' );
+
+ if ( !$fp_out ) {
+ $fp_out = null;
+ throw new RuntimeException( 'IOException. Unable to create temporary file.' );
+ }
+
+ $tmpFileObject = new SplFileObject( $filePath, 'r' );
+
+ while ( !$tmpFileObject->eof() ) {
+ gzwrite( $fp_out, $tmpFileObject->fgets() );
+ }
+
+ $tmpFileObject = null;
+ gzclose( $fp_out );
+
+ $clientMemories->importTmx( 'ext_my_' . $memoryKey, "$filePath.gz", true );
+
+ $fp_out = null;
+
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function delete( $_config ) {
+ // TODO: Implement delete() method.
+ }
+
+ /**
+ * @param array $_keys
+ *
+ * @return array
+ */
+ protected function _reMapKeyList( array $_keys = [] ): array {
+
+ if ( !empty( $_keys ) ) {
+
+ if ( !is_array( $_keys ) ) {
+ $_keys = [ $_keys ];
+ }
+
+ $_keys = array_map( function ( $key ) {
+ return 'ext_my_' . $key;
+ }, $_keys );
+
+ }
+
+ return $_keys;
+
+ }
+
+}
\ No newline at end of file
diff --git a/lib/Utils/Engines/MMT.php b/lib/Utils/Engines/MMT.php
index 6d8d54d832..7a71439683 100644
--- a/lib/Utils/Engines/MMT.php
+++ b/lib/Utils/Engines/MMT.php
@@ -1,6 +1,7 @@
null,
'translation' => null,
@@ -45,7 +53,7 @@ public function __construct( $engineRecord ) {
throw new Exception( "Engine {$this->engineRecord->id} is not a MT engine, found {$this->engineRecord->type} -> {$this->engineRecord->class_load}" );
}
- if ( isset( $this->engineRecord->extra_parameters[ 'MMT-pretranslate' ] ) && $this->engineRecord->extra_parameters[ 'MMT-pretranslate' ] == true ) {
+ if ( isset( $this->engineRecord->extra_parameters[ 'MMT-pretranslate' ] ) && $this->engineRecord->extra_parameters[ 'MMT-pretranslate' ] ) {
$this->_skipAnalysis = false;
}
@@ -80,7 +88,7 @@ protected function _getClient() {
* Get the available languages in MMT
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
*/
public function getAvailableLanguages() {
$client = $this->_getClient();
@@ -92,6 +100,7 @@ public function getAvailableLanguages() {
* @param $_config
*
* @return array|Engines_Results_AbstractResponse
+ * @throws ReflectionException
*/
public function get( $_config ) {
@@ -103,6 +112,20 @@ public function get( $_config ) {
$client = $this->_getClient();
$_keys = $this->_reMapKeyList( $_config[ 'keys' ] ?? [] );
+ $metadata = null;
+ if ( !empty( $_config[ 'project_id' ] ) ) {
+ $metadataDao = new Projects_MetadataDao();
+ $metadata = $metadataDao->setCacheTTL( 86400 )->get( $_config[ 'project_id' ], 'mmt_glossaries' );
+ }
+
+ if ( $metadata !== null ) {
+ $metadata = html_entity_decode( $metadata->value );
+ $mmtGlossariesArray = json_decode( $metadata, true );
+
+ $_config[ 'glossaries' ] = implode( ",", $mmtGlossariesArray[ 'glossaries' ] );
+ $_config[ 'ignore_glossary_case' ] = $mmtGlossariesArray[ 'ignore_glossary_case' ];
+ }
+
try {
$translation = $client->translate(
$_config[ 'source' ],
@@ -141,11 +164,11 @@ public function get( $_config ) {
}
/**
- * @param $_keys
+ * @param array $_keys
*
* @return array
*/
- protected function _reMapKeyList( $_keys = [] ) {
+ protected function _reMapKeyList( array $_keys = [] ): array {
if ( !empty( $_keys ) ) {
@@ -204,7 +227,7 @@ public function set( $_config ) {
public function update( $_config ) {
$client = $this->_getClient();
- $_keys = $this->_reMapKeyList( @$_config[ 'keys' ] );
+ $_keys = $this->_reMapKeyList( $_config[ 'keys' ] ?? [] );
try {
$client->updateMemoryContent(
@@ -217,7 +240,7 @@ public function update( $_config ) {
$_config[ 'session' ]
);
} catch ( Exception $e ) {
- return false;
+ return false; // requeue
}
return true;
@@ -229,55 +252,66 @@ public function delete( $_config ) {
}
/**
- * @param $filePath
- * @param $key
- * @param bool $fileName
*
- * @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @param string $filePath
+ * @param string $memoryKey
+ * @param Users_UserStruct $user *
+ *
+ * @return void
+ * @throws MMTServiceApiException
+ * @throws Exception
*/
- public function import( $filePath, $key, $fileName = false ) {
+ public function importMemory( string $filePath, string $memoryKey, Users_UserStruct $user ) {
+
+ $client = $this->_getClient();
+
+ $associatedMemories = $client->getAllMemories();
+ $memoryFound = false;
+
+ foreach ( $associatedMemories as $memory ) {
+ if ( 'x_mm-' . trim( $memoryKey ) === $memory[ 'externalId' ] ) {
+ $memoryFound = true;
+ break;
+ }
+ }
+
+ if ( !$memoryFound ) {
+ return null;
+ }
$fp_out = gzopen( "$filePath.gz", 'wb9' );
if ( !$fp_out ) {
$fp_out = null;
- @unlink( $filePath );
- $filePath = null;
- @unlink( "$fileName.gz" );
throw new RuntimeException( 'IOException. Unable to create temporary file.' );
}
- $tmpFileObject = new \SplFileObject( $filePath, 'r' );
+ $tmpFileObject = new SplFileObject( $filePath, 'r' );
while ( !$tmpFileObject->eof() ) {
gzwrite( $fp_out, $tmpFileObject->fgets() );
}
$tmpFileObject = null;
- @unlink( $filePath );
gzclose( $fp_out );
- $client = $this->_getClient();
- $client->importIntoMemoryContent( 'x_mm-' . trim( $key ), "$filePath.gz", 'gzip' );
+ $client->importIntoMemoryContent( 'x_mm-' . trim( $memoryKey ), "$filePath.gz", 'gzip' );
$fp_out = null;
- @unlink( "$filePath.gz" );
- return $this->result;
}
/**
*
- * @param $file \SplFileObject
+ * @param $file SplFileObject
* @param $source string
* @param $targets string[]
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
* @internal param array $langPairs
*
*/
- public function getContext( \SplFileObject $file, $source, $targets ) {
+ public function getContext( SplFileObject $file, $source, $targets ) {
$fileName = $file->getRealPath();
$file->rewind();
@@ -314,7 +348,7 @@ public function getContext( \SplFileObject $file, $source, $targets ) {
/**
* Call to check the license key validity
* @return Engines_Results_MMT_ExceptionError
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
* @throws Exception
*/
public function checkAccount() {
@@ -334,7 +368,7 @@ public function checkAccount() {
* @param $keyList TmKeyManagement_MemoryKeyStruct[]
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
*/
public function connectKeys( array $keyList ) {
@@ -402,7 +436,7 @@ protected function _decode( $rawValue, array $parameters = [], $function = null
* @param null $externalId
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
*/
public function createMemory( $name, $description = null, $externalId = null ) {
$client = $this->_getClient();
@@ -417,7 +451,7 @@ public function createMemory( $name, $description = null, $externalId = null ) {
* @param $id
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
*/
public function deleteMemory( $id ) {
$client = $this->_getClient();
@@ -430,7 +464,7 @@ public function deleteMemory( $id ) {
* (id can be an external account)
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
*/
public function getAllMemories() {
$client = $this->_getClient();
@@ -445,7 +479,7 @@ public function getAllMemories() {
* @param $id
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
*/
public function getMemory( $id ) {
$client = $this->_getClient();
@@ -458,7 +492,7 @@ public function getMemory( $id ) {
* @param $name
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
*/
public function updateMemory( $id, $name ) {
$client = $this->_getClient();
@@ -471,7 +505,7 @@ public function updateMemory( $id, $name ) {
* @param $data
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
*/
public function importGlossary( $id, $data ) {
$client = $this->_getClient();
@@ -484,7 +518,7 @@ public function importGlossary( $id, $data ) {
* @param $data
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
*/
public function updateGlossary( $id, $data ) {
$client = $this->_getClient();
@@ -496,7 +530,7 @@ public function updateGlossary( $id, $data ) {
* @param $uuid
*
* @return mixed
- * @throws \Engines\MMT\MMTServiceApiException
+ * @throws MMTServiceApiException
*/
public function importJobStatus( $uuid ) {
$client = $this->_getClient();
diff --git a/lib/Utils/Engines/MyMemory.php b/lib/Utils/Engines/MyMemory.php
index 1d27392157..93be3f1ecb 100644
--- a/lib/Utils/Engines/MyMemory.php
+++ b/lib/Utils/Engines/MyMemory.php
@@ -15,6 +15,13 @@
*/
class Engines_MyMemory extends Engines_AbstractEngine {
+ /**
+ * @inheritdoc
+ * @see Engines_AbstractEngine::$_isAdaptive
+ * @var bool
+ */
+ protected bool $_isAdaptive = true;
+
/**
* @var string
*/
@@ -606,12 +613,19 @@ public function glossaryUpdate( $idSegment, $idJob, $password, $term ) {
return $this->result;
}
- public function import( $file, $key, $name = false ) {
+ /**
+ *
+ * @param string $filePath
+ * @param string $memoryKey
+ * @param Users_UserStruct $user * Not used
+ *
+* @return array|mixed
+ */
+ public function importMemory( string $filePath, string $memoryKey, Users_UserStruct $user) {
$postFields = [
- 'tmx' => $this->getCurlFile( $file ),
- 'name' => $name,
- 'key' => trim( $key )
+ 'tmx' => $this->getCurlFile( $filePath ),
+ 'key' => trim( $memoryKey )
];
$this->call( "tmx_import_relative_url", $postFields, true );
diff --git a/lib/Utils/ProjectManager.php b/lib/Utils/ProjectManager.php
index 26bc1c57d4..0b2503c56d 100644
--- a/lib/Utils/ProjectManager.php
+++ b/lib/Utils/ProjectManager.php
@@ -1195,8 +1195,8 @@ protected function _pushTMXToMyMemory() {
$this->getSingleS3QueueFile( $fileName );
}
- $this->tmxServiceWrapper->addTmxInMyMemory( $file );
- $this->features->run( 'postPushTMX', $file, $this->projectStructure[ 'id_customer' ] );
+ $userStruct = ( new Users_UserDao() )->setCacheTTL( 60 * 60 )->getByUid( $this->projectStructure[ 'uid' ] );
+ $this->tmxServiceWrapper->addTmxInMyMemory( $file, $userStruct );
} else {
//don't call the postPushTMX for normal files
diff --git a/lib/Utils/TMS/TMSService.php b/lib/Utils/TMS/TMSService.php
index 1ca96283c8..1db33a930e 100644
--- a/lib/Utils/TMS/TMSService.php
+++ b/lib/Utils/TMS/TMSService.php
@@ -4,6 +4,7 @@
use API\Commons\Exceptions\UnprocessableException;
use Chunks_ChunkDao;
+use Constants_Engines;
use Constants_TranslationStatus;
use DateTime;
use DateTimeZone;
@@ -11,6 +12,7 @@
use Engines_MyMemory;
use Engines_Results_MyMemory_ExportResponse;
use Engines_Results_MyMemory_TmxResponse;
+use EnginesModel_EngineStruct;
use Exception;
use FeatureSet;
use INIT;
@@ -22,6 +24,8 @@
use stdClass;
use TMSService\TMSServiceDao;
use Upload;
+use Users\MetadataDao;
+use Users_UserStruct;
use Utils;
class TMSService {
@@ -143,29 +147,68 @@ public function uploadFile() {
* Import TMX file in MyMemory
* @throws Exception
*/
- public function addTmxInMyMemory( TMSFile $file ) {
+ public function addTmxInMyMemory( TMSFile $file, Users_UserStruct $user ) {
- $this->checkCorrectKey( $file->getTmKey() );
+ try {
- Log::doJsonLog( $this->file );
+ $this->checkCorrectKey( $file->getTmKey() );
- $importStatus = $this->mymemory_engine->import(
- $file->getFilePath(),
- $file->getTmKey(),
- $file->getName()
- );
+ Log::doJsonLog( $this->file );
- //check for errors during the import
- switch ( $importStatus->responseStatus ) {
- case "503" :
- case "400" :
- throw new Exception( "Error uploading TMX file. Please, try again in 5 minutes.", -15 );
- case "403" :
- throw new Exception( "Error: " . $this->formatErrorMessage( $importStatus->responseDetails ), -15 );
- default:
- }
+ $importStatus = $this->mymemory_engine->importMemory(
+ $file->getFilePath(),
+ $file->getTmKey(),
+ $user
+ );
- $file->setUuid( $importStatus->id );
+ //check for errors during the import
+ switch ( $importStatus->responseStatus ) {
+ case "503" :
+ case "400" :
+ throw new Exception( "Error uploading TMX file. Please, try again in 5 minutes.", -15 );
+ case "403" :
+ throw new Exception( "Error: " . $this->formatErrorMessage( $importStatus->responseDetails ), -15 );
+ default:
+ }
+
+ $file->setUuid( $importStatus->id );
+
+ // load tmx in engines with adaptivity
+ $engineList = Constants_Engines::getAvailableEnginesList();
+
+ foreach ( $engineList as $engineName ) {
+
+ try {
+
+ $struct = EnginesModel_EngineStruct::getStruct();
+ $struct->class_load = $engineName;
+ $struct->type = Constants_Engines::MT;
+ $engine = Engine::createTempInstance( $struct );
+
+ if ( $engine->isAdaptive() ) {
+ //retrieve OWNER Engine License
+ $ownerMmtEngineMetaData = ( new MetadataDao() )->setCacheTTL( 60 * 60 * 24 * 30 )->get( $user->uid, $engine->getEngineRow()->class_load ); // engine_id
+ if ( !empty( $ownerMmtEngineMetaData ) ) {
+ $engine = Engine::getInstance( $ownerMmtEngineMetaData->value );
+
+ Log::doJsonLog( "User [$user->uid, '$user->email'] start importing memory: {$engine->getEngineRow()->class_load} -> " . $file->getFilePath() . " -> " . $file->getTmKey() );
+ $engine->importMemory( $file->getFilePath(), $file->getTmKey(), $user );
+
+ }
+ }
+
+ } catch ( Exception $e ) {
+ if ( $engineName != Constants_Engines::MY_MEMORY ) {
+ Log::doJsonLog( $e->getMessage() );
+ }
+ }
+
+ }
+
+ } finally {
+ @unlink( $file->getFilePath() );
+ @unlink( $file->getFilePath() . ".gz" );
+ }
}
diff --git a/lib/Utils/TmKeyManagement/TmKeyManagement.php b/lib/Utils/TmKeyManagement/TmKeyManagement.php
index 9c1a94dff8..63662f62ac 100644
--- a/lib/Utils/TmKeyManagement/TmKeyManagement.php
+++ b/lib/Utils/TmKeyManagement/TmKeyManagement.php
@@ -159,7 +159,7 @@ public static function getOwnerKeys( Array $jsonTmKeys_array, $grant_level = 'rw
//convert tm keys into TmKeyManagement_TmKeyStruct objects
$result_arr = array_map( array( 'self', 'getTmKeyStructure' ), $result_arr );
- return $result_arr;
+ return array_values( $result_arr );
}
/**
diff --git a/lib/Utils/Utils.php b/lib/Utils/Utils.php
index 1e8b7e8ef0..0bce8d24d4 100644
--- a/lib/Utils/Utils.php
+++ b/lib/Utils/Utils.php
@@ -814,18 +814,6 @@ public static function truncatePhrase( string $phrase, int $max_words ): string
return $phrase;
}
- /**
- * This escape is need by
- * javascript JSON.parse() function
- *
- * @param array $data
- *
- * @return string
- */
- public static function escapeJsonEncode( array $data ): string {
- return str_replace( "\\\"", "\\\\\\\"", json_encode( $data ) );
- }
-
/**
* This function strips html tag, but preserves hrefs.
*
diff --git a/lib/View/API/V2/Json/Engine.php b/lib/View/API/V2/Json/Engine.php
index bfd2b95ddf..b70a337195 100644
--- a/lib/View/API/V2/Json/Engine.php
+++ b/lib/View/API/V2/Json/Engine.php
@@ -25,12 +25,13 @@ public function __construct( $data = null ) {
* @return array
*/
public function renderItem( EnginesModel_EngineStruct $engine ) {
+ $engine_type = explode( "\\", $engine->class_load );
return [
'id' => $engine->id,
'name' => $engine->name,
'type' => $engine->type,
'description' => $engine->description,
- 'engine_type' => $engine->class_load,
+ 'engine_type' => array_pop( $engine_type )
];
}
diff --git a/lib/View/templates/_index.html b/lib/View/templates/_index.html
index a8def86491..20cbc73f55 100755
--- a/lib/View/templates/_index.html
+++ b/lib/View/templates/_index.html
@@ -36,7 +36,6 @@
isOpenAiEnabled: ${isOpenAiEnabled},
maxFileSize: ${maxFileSize},
maxTMXFileSize: ${maxTMXFileSize},
- maxNumSegments: ${maxNumSegments},
id_customer: '${id_customer | string:unknown_customer}',
private_customer: '${private_customer | string:0}',
first_job_segment: '${first_job_segment}',
@@ -49,7 +48,7 @@
analysis_enabled: '${analysis_enabled}',
not_empty_default_tm_key: ${not_empty_default_tm_key|string:false},
footer_show_revise_link: ${footer_show_revise_link || string: false},
- intento_providers: JSON.parse('${translation_engines_intento_prov_json}'),
+ intento_providers: JSON.parse(String.raw`${php: json_encode(translation_engines_intento_providers)}`),
get job_id() {
console.info('job_id is deprecated, use id_job instead', getStackTrace().split("\n")[2]);
return this.id_job ;
@@ -85,7 +84,7 @@
mark_as_complete_button_enabled : ${mark_as_complete_button_enabled | 'false'},
status_labels : JSON.parse( '${status_labels}' ),
searchable_statuses : JSON.parse( '${ php: json_encode(searchable_statuses)}'),
- active_engine: JSON.parse('${active_engine}'),
+ active_engine: JSON.parse(String.raw`${php: json_encode(active_engine)}`),
isGDriveProject : ${isGDriveProject|string:false},
remoteFilesInJob : JSON.parse( '${ php: json_encode(remoteFilesInJob)}'),
translation_matches_enabled : ${translation_matches_enabled} ,
diff --git a/plugins/aligner b/plugins/aligner
index 5c41058446..7adf6b326e 160000
--- a/plugins/aligner
+++ b/plugins/aligner
@@ -1 +1 @@
-Subproject commit 5c410584467816b0df746d17e5462b440ecb22f6
+Subproject commit 7adf6b326e5ea91e93b857e9a94f3661cf4a020a
diff --git a/public/css/sass/components/settingsPanel/MachineTranslationTab.scss b/public/css/sass/components/settingsPanel/MachineTranslationTab.scss
index 8dfefd3a5f..91ea207ee7 100644
--- a/public/css/sass/components/settingsPanel/MachineTranslationTab.scss
+++ b/public/css/sass/components/settingsPanel/MachineTranslationTab.scss
@@ -125,6 +125,12 @@
}
}
}
+
+ .provider-field-row {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ }
}
.machine-translation-tab-table-title {
display: flex;
@@ -196,6 +202,21 @@
.add-mt-provider .select-with-label__wrapper {
margin-right: 30px;
}
+
+ .provider-license-label-with-icon {
+ display: flex;
+ gap: 5px;
+ }
+
+ .provider-data-lara {
+ .button {
+ margin-top: 62px !important;
+ }
+
+ .provider-field {
+ gap: 15px !important;
+ }
+ }
}
.machine-translation-tab {
.settings-panel-table-rowHeading,
diff --git a/public/js/cat_source/es6/api/convertFileRequest/convertFileRequest.js b/public/js/cat_source/es6/api/convertFileRequest/convertFileRequest.js
index 39409877fb..7cf99724ad 100644
--- a/public/js/cat_source/es6/api/convertFileRequest/convertFileRequest.js
+++ b/public/js/cat_source/es6/api/convertFileRequest/convertFileRequest.js
@@ -19,7 +19,7 @@ export const convertFileRequest = async ({
segmentation_rule,
filters_extraction_parameters_template_id,
signal,
- restarted_conversion
+ restarted_conversion,
}) => {
const dataParams = {
action,
@@ -28,7 +28,7 @@ export const convertFileRequest = async ({
target_lang,
segmentation_rule,
filters_extraction_parameters_template_id,
- restarted_conversion
+ restarted_conversion,
}
const formData = new FormData()
diff --git a/public/js/cat_source/es6/api/getContributions/getContributions.js b/public/js/cat_source/es6/api/getContributions/getContributions.js
index 5886f30209..152d8bc72b 100644
--- a/public/js/cat_source/es6/api/getContributions/getContributions.js
+++ b/public/js/cat_source/es6/api/getContributions/getContributions.js
@@ -22,19 +22,20 @@ export const getContributions = async ({
password = config.password,
idClient = config.id_client,
currentPassword = config.currentPassword,
+ contextListBefore,
+ contextListAfter,
}) => {
const contextBefore = UI.getContextBefore(idSegment)
const idBefore = UI.getIdBefore(idSegment)
const contextAfter = UI.getContextAfter(idSegment)
const idAfter = UI.getIdAfter(idSegment)
- const txt = target
const obj = {
action: 'getContribution',
password: password,
is_concordance: 0,
id_segment: idSegment,
- text: txt,
+ text: target,
id_job: idJob,
num_results: NUM_CONTRIBUTION_RESULTS,
context_before: contextBefore ? contextBefore : '',
@@ -44,6 +45,8 @@ export const getContributions = async ({
id_client: idClient,
cross_language: crossLanguages,
current_password: currentPassword,
+ context_list_before: JSON.stringify(contextListBefore),
+ context_list_after: JSON.stringify(contextListAfter),
}
const dataParams = Object.fromEntries(
Object.entries(obj).filter(([_, v]) => v != null),
diff --git a/public/js/cat_source/es6/components/segments/SegmentFooterTabMatches.js b/public/js/cat_source/es6/components/segments/SegmentFooterTabMatches.js
index 7fd07f6e40..9346caf931 100644
--- a/public/js/cat_source/es6/components/segments/SegmentFooterTabMatches.js
+++ b/public/js/cat_source/es6/components/segments/SegmentFooterTabMatches.js
@@ -37,7 +37,7 @@ class SegmentFooterTabMatches extends React.Component {
var item = {}
item.id = this.id
item.disabled = this.id == '0' ? true : false
- item.cb = this.created_by
+ item.cb = this.created_by === 'MT-Lara' ? 'Lara' : this.created_by
item.segment = this.segment
item.translation = this.translation
item.target = this.target
diff --git a/public/js/cat_source/es6/components/segments/utils/translationMatches.js b/public/js/cat_source/es6/components/segments/utils/translationMatches.js
index 30d00bf843..567cb135fb 100644
--- a/public/js/cat_source/es6/components/segments/utils/translationMatches.js
+++ b/public/js/cat_source/es6/components/segments/utils/translationMatches.js
@@ -189,13 +189,16 @@ let TranslationMatches = {
console.log('SSE: ID_CLIENT not found')
return Promise.resolve()
}
-
+ const {contextListBefore, contextListAfter} =
+ SegmentUtils.getSegmentContext(id_segment_original)
return getContributions({
idSegment: id_segment_original,
target: currentSegment.segment,
crossLanguages: crossLanguageSettings
? [crossLanguageSettings.primary, crossLanguageSettings.secondary]
: [],
+ contextListBefore,
+ contextListAfter,
}).catch((errors) => {
UI.processErrors(errors, 'getContribution')
TranslationMatches.renderContributionErrors(errors, id_segment_original)
diff --git a/public/js/cat_source/es6/components/settingsPanel/Contents/MachineTranslationTab/MTRow.js b/public/js/cat_source/es6/components/settingsPanel/Contents/MachineTranslationTab/MTRow.js
index 8932be6fc8..205a0f9327 100644
--- a/public/js/cat_source/es6/components/settingsPanel/Contents/MachineTranslationTab/MTRow.js
+++ b/public/js/cat_source/es6/components/settingsPanel/Contents/MachineTranslationTab/MTRow.js
@@ -36,6 +36,11 @@ export const MTRow = ({row, deleteMT, onCheckboxClick}) => {
+ * {
* "en":["it","zh-TW"],
* "de":["en"]
- * }
- *
+ * }
+ *
+ Lara is a groundbreaking machine translation engine
+ powered by Large Language Models. It surpasses traditional machine
+ translation by understanding context and learning from previously
+ translated content, delivering high-quality, nuanced translations.
+
+ Lara currently supports all combinations of ten languages, with more
+ on the way soon. For languages not yet supported, translation is
+ provided through ModernMT Lite, or your personal ModernMT Full if a
+ valid license is provided.
+
+ Lara is only available for machine translation post-editing,
+ pre-translation is always performed with ModernMT.
+