<?php
namespace App\Controller;
use Symfony\Component\String\UnicodeString;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\Filesystem\Filesystem;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use App\Entity\DocumentDictionary as DocumentDictionary;
use App\Entity\TranslationDictionary;
use App\Entity\User;
use Exception;
use Doctrine\ORM\EntityManagerInterface;
use App\Service\utiltranslate;
use App\Service\requestTranslation;
use App\Message\Notify;
use deeplcom\deepl;
class TranslateController extends AbstractController
{
private $em;
private $utiltranslate;
private $requestTranslation;
public function __construct(EntityManagerInterface $em, utiltranslate $utiltranslate, requestTranslation $requestTranslation)
{
$this->em = $em;
$this->utiltranslate= $utiltranslate;
$this->requestTranslation=$requestTranslation;
}
/**
* @Route("/translate/show/{id}", name="showTranslate")
* @Template("dictionary/translate.html.twig")
*/
public function showAction($id = null)
{
list($documents, $projects) = $this->utiltranslate->getProjectsyDocuments();
if ($id) {
$em = $this->getDoctrine()->getManager();
$document = $em->getRepository(DocumentDictionary::class)->find($id);
if ($document) {
$original = $document->getBaseText();
$documentName = $document->getName();
$projectName = $document->getProject()->getName();
} else {
throw $this->createNotFoundException('El documento no existe');
}
} else {
$original = "";
$documentName = "";
$projectName = "";
}
return array(
'documents' => $documents,
'projects' => $projects,
'original' => $original,
'documentName' => $documentName,
'projectName' => $projectName
);
}
/**
* @Route("/translate/getDocumentsOfProject", name="getDocumentsOfProject")
*/
public function getDocumentsOfProject()
{
$result = $this->utiltranslate->getDocumentsEntitiesOfProject($_POST['project']);
$documents = array();
if ($result) {
$documents = $result[0]['documents'];
foreach ($documents as $key => $document) {
if ($document['deadLine']) $date = $document['deadLine']->format('d/m/Y');
else $date = "";
$documents[$key]['date'] = $date;
}
} else {
$documents[] = array("name"=>"","date"=>"");
}
return new Response(json_encode($documents));
}
private function formatJumpLines($subject)
{
$search = array("</li>", "</p>", "</td>", "}}", "<br />", "<br/>","<br>");
$replace = array("</li>\n", "</p>\n", "</td>\n", "}}\n", "\n", "\n","\n");
$textReturn = str_replace($search, $replace, $subject);
return $textReturn;
}
/**
* Recoge los datos recibidos por post y modifica las variables por referencia con los valores obtenidos.
* @param type $languages
* @param type $originalText
*/
private function getDataPostTranslate($DDBBLanguages, &$languages, &$isArticle, &$originalText)
{
$originalText = $_POST['original'];
foreach ($DDBBLanguages as $DDBBLaguage) {
$check = ucfirst($DDBBLaguage) . "Check";
if ((isset($_POST[$check])) && ($_POST[$check]) !== "false")
$languages[$DDBBLaguage] = $DDBBLaguage;
}
if (isset($_POST["isArticle"])) $isArticle = filter_var($_POST["isArticle"], FILTER_VALIDATE_BOOLEAN);
else $isArticle = false;
}
private function getDataPostCreate()
{
if (isset($_POST['original'])) $fullText = $_POST['original'];
else $fullText = "";
if (isset($_POST['project'])) $projectName = $_POST['project'];
else $projectName = "No hay proyecto";
if (isset($_POST['documento'])) $documentName = $_POST['documento'];
else $documentName = "No hay documento";
if (isset($_POST['datepicker']))
$date = \DateTime::createFromFormat('d/m/Y', $_POST['datepicker']);
else
$date = null;
if (isset($_POST["isArticle"])) $isArticle = $_POST["isArticle"];
else $isArticle = false;
$langs=$this->getLanguajesFromPost();
$userId = $this->getUser()->getId();
$data = array( "fullText"=>$fullText,
"deadLine"=>$date,
"projectName"=>$projectName,
"documentName"=>$documentName,
"langs"=>$langs,
"userId"=>$userId);
return array($data, $isArticle);
}
private function getLanguajesFromPost(){
$langsToTranslate=array();
$languajes=$this->requestTranslation->getLanguajes();
//Obtenemos los lenguajes de la base de datos y comporbamos en los que se ha solicitado la traducción.
foreach ($languajes as $languaje) {
$check = ucfirst($languaje) . "Check";
if ((isset($_POST[$check])) && ($_POST[$check]) !== "false")
$langsToTranslate[] = $languaje;
}
return $langsToTranslate;
}
/**
* @Route("/translate/translate", name="translateAction")
* Recoge los datos de la vista de traducciones y las procesa devolviendo
* las que estén traducidas, en las que no, indica naranja si la traducción está
* pendiente, rojo si la traducción no se ha creado o gris si ha habido algún error.
*/
public function translateAction()
{
//Si no se envían datos por post no se hace nada.
if (isset($_POST['original'])) {
$DDBBLanguages = $this->em->getRepository(TranslationDictionary::class)->getLanguages();
$languages = array();
$fullText = "";
//Obtenemos los valores de POST y modificamos las variables por referencia.
$this->getDataPostTranslate($DDBBLanguages, $languages, $isArticle, $fullText);
//Quitamos las etiquetas HTML y sustituimos los br por saltos de linea.
if ($isArticle) {
$response = $this->requestTranslation->translateArticle($fullText, $languages, NULL, NULL);
} else {
if (isset($_POST['project']) && is_string($_POST['project'])) $projectName= $_POST['project'];
else $projectName = "Project no definido";
if (isset($_POST['document']) && is_string($_POST['document'])) $documentName= $_POST['document'];
else $documentName = "Documento no definido";
$response = $this->requestTranslation->translateSentences($fullText, $languages, $DDBBLanguages, null, true, $projectName, $documentName);
}
$json_response = json_encode($response);
return new Response($json_response);
} else {
return new Response("Error");
}
}
/**
* @Route("/falang/translate", name="translateFalang")
*
*/
public function translateFalang()
{
//$textPrueba = '{"falangData":{"lang":"de","data":{"virtuemart_product_id":"325","product_name":"A11","reference_field":"product_desc","product_desc":"<ul><li> Grabador NVR para cámaras IP<br /></li><li> 4 CH vídeo IP<br /></li><li> Resolución máxima grabación 5 Mpx<br /></li><li> Ancho de banda 80 Mbps<br /></li><li> Salida VGA y HDMI Full HD<br /></li><li> Admite 1 disco duro</ul>","language_id":"1"}}}';
//$input = json_decode($textPrueba,true);
//Si no se envían datos por post no se hace nada.
$input = json_decode(file_get_contents("php://input"), true);
//var_dump($input);
if (isset($input['falangData'])) {
$em = $this->getDoctrine()->getManager();
$DDBBLanguages = $em->getRepository(TranslationDictionary::class)->getLanguages();
//Obtenemos los valores de POST.
$falangData = $input['falangData'];
$data = $falangData["data"];
$lang = $falangData["lang"];
$response = array();
foreach ($data as $datum) {
$referenceField = $datum["reference_field"];
//Si la traducción es el nombre, se envía la traducción directamente.
if ($referenceField == "product_name") {
$response[] = $this->getReferenceResponse($datum);
} else {
$response[] = $this->translateFalangText($datum[$referenceField], $datum["product_name"], $referenceField, $lang, $this->utiltranslate, $datum["virtuemart_product_id"], $em);
}
}
$fullResponse["response"] = $response;
$fullResponse["lang"] = $lang;
$countryCode = $falangData["country_code"];
$curl = $this->sendResponse(json_encode($fullResponse), $countryCode);
//Enviamos a la nueva herramienta las traducciones
//$this->createNewTTTranslation($data, $lang);
if (!$curl) {
return new Response("Problema al enviar la respuesta " . json_encode($fullResponse));
} else {
return new Response("Terminado con éxito en intranet");
}
} else {
return new Response("No se han enviado datos por POST");
}
}
/**
* @Route("/falang/translate/category", name="translateFalangCategory")
* Función para gestionar las traducciones de categorías de la web
*/
public function translateFalangCategory()
{
//$textPrueba = '{"falangData":{"lang":"de","data":{"virtuemart_product_id":"325","product_name":"A11","reference_field":"product_desc","product_desc":"<ul><li> Grabador NVR para cámaras IP<br /></li><li> 4 CH vídeo IP<br /></li><li> Resolución máxima grabación 5 Mpx<br /></li><li> Ancho de banda 80 Mbps<br /></li><li> Salida VGA y HDMI Full HD<br /></li><li> Admite 1 disco duro</ul>","language_id":"1"}}}';
//$input = json_decode($textPrueba,true);
//Si no se envían datos por post no se hace nada.
$input = json_decode(file_get_contents("php://input"), true);
//var_dump($input);
if (isset($input['falangData'])) {
$DDBBLanguages = $this->em->getRepository(TranslationDictionary::class)->getLanguages();
ob_start();
//Obtenemos los valores de POST.
$falangData = $input['falangData'];
$categoryName = $falangData["categoryName"];
$categoryId = $falangData["categoryId"];
//echo "La categoria es: ".$categoryName;
$response = array();
$user = $this->em->getRepository(User::class)->find(5);
$fullResponse = array();
foreach ($DDBBLanguages as $lang) {
$response = $this->translateFalangCategoryName($categoryName, $categoryId, $lang, $this->utiltranslate, $DDBBLanguages, $user, $em);
$fullResponse[$lang] = $response;
}
//$curl = $this->sendResponse(json_encode($fullResponse));
ob_end_clean();
return new Response(json_encode($fullResponse));
} else {
return new Response("No se han enviado datos por POST");
}
}
private function getReferenceResponse($datum)
{
$reference = $datum["product_name"];
$fullResponse["response"] = $reference;
$fullResponse["reference_field"] = $datum["reference_field"];
$fullResponse["state"] = "ready";
$fullResponse["reference"] = $reference;
$fullResponse["productId"] = $datum["virtuemart_product_id"];
$fullResponse["originalValue"] = $reference;
return $fullResponse;
}
/**
* @param $fullText
* @param $reference
* @param $referenceField
* @param $lang
* @param $this->utiltranslate
* @param $productId
* @param $em
* @return mixed
* Traduce las fichas de productos de la web
*/
private function translateFalangText($fullText, $reference, $referenceField, $lang, $productId, $em)
{
$formated = $this->formatJumpLines($fullText);
$noTags = strip_tags($formated);
$response = "";
//Comprobamos que sin las etiquetas HTMl no se quede sin contenido.
if (trim($noTags) !== "") {
$user = $this->em->getRepository(User::class)->find(5);
//Inicializamos la posisicion de reemplazo.
$posGlobal = 0;
//separamos el texto en frases.
$splittedText = $this->requestTranslation->splitText($noTags);
//Eliminamos el espacio en blanco maligno
$noEvilSpaces = str_replace(array(" ", " "), " ", $splittedText);
//if($referenceField =="product_s_desc") echo $referenceField." | ". var_dump($splittedText);
$response = html_entity_decode($fullText, ENT_QUOTES, "UTF-8");
//cogemos el proyecto y creamos el documento si es necesario.
$project = $this->utiltranslate->createProject("Web");
$document = $this->utiltranslate->createDocument($reference, $project, $user);
$send = false;
$DDBBLangs = null;
$state = "ready";
//Procesamos cada frase.
foreach ($noEvilSpaces as $originalText) {
//quitamos los espacios en blanco normales el principio y al final de las frases.
$originalText = html_entity_decode(trim($originalText, " ."), ENT_QUOTES, "UTF-8");
// echo "el original es: ".$originalText."<br>";
if ($originalText !== "") {
usleep(300);
list($encontrado, $matches) = $this->utiltranslate->encontrarOriginal($originalText);
//$encontrado = $this->utiltranslate->findOriginal($originalText);
if ($encontrado) //Si el orgininal está registrado
{
//Obtiene las traducciones si están traducidas. Si no, devuelve -1 o -2.
$translation = $this->utiltranslate->getTranslation(
$originalText,
$lang,
$encontrado,
$matches
);
//Si falta por crear la traducción la añadimos al original.
if ($translation === -3) {
$this->utiltranslate->createDictionary(
$originalText,
"Web",
$reference,
array($lang),
$project,
$document,
$user
);
$send = true;
$state = "pending";
echo "Faltaba por crear la traducción para el original es: " . $originalText . " (" . $reference . ") <br/>";
} else if ($translation === -2) {
$state = "pending";
echo "Traducción pendiente para: " . $originalText . "(" . $reference . "). Estado: " . $translation . "<br>";
}
//echo "La traducción ".$translation." <br>";
//Marcamos la respuesta con el color correspondiente
$translation = $this->requestTranslation->manageTranslation($originalText, $translation);
$response = $this->requestTranslation->replace($originalText, $translation, $response, $posGlobal, $reference);
//Función para formatear el estado de la traducción.
$posGlobal += strlen($translation) - 1;
} else {
//si el original no existe, lo tenemos que crear y mandamos la respuesta vacia.
$send = true;
$state = "pending";
echo "Creamos el original (" . $originalText . ") (" . $reference . ")<br>";
$DDBBLangs = $this->utiltranslate->getLanguagesAction();
//Función para crear el original y la traducción en TODOS los idiomas.
$this->utiltranslate->createDictionary(
$originalText,
"Web",
$reference,
$DDBBLangs,
$project,
$document,
$user
);
$error = $this->requestTranslation->marcarError($originalText);
$response = $this->requestTranslation->replace($originalText, $error, $response, $posGlobal, $reference);
$posGlobal += strlen($error) - 1;
}
}
}
//Si hay idiomas es que se ha creado un original.
if ($DDBBLangs) {
$this->utiltranslate->sendNewTranslations($DDBBLangs);
}
//Si no hay idiomas y se ha marcado el send se manda en el idioma en concreto.
else if ($send) {
$this->utiltranslate->sendNewTranslations(array($lang));
}
} else { // Si el texto enviado está vacío no se hace nada.
$response = "El POST no contiene mensaje";
$state = "pending";
}
$fullResponse["response"] = $response;
$fullResponse["reference_field"] = $referenceField;
$fullResponse["state"] = $state;
$fullResponse["reference"] = $reference;
$fullResponse["productId"] = $productId;
$fullResponse["originalValue"] = $fullText;
return $fullResponse;
}
private function translateFalangCategoryName($categoryName, $categoryId, $lang, $DDBBLangs, $user, $em)
{
$categoryName = trim($categoryName);
$response = "";
$documentName = $categoryName . "-" . $categoryId;
if ($categoryName !== "") {
$project = $this->utiltranslate->createProject("WebCategories");
$document = $this->utiltranslate->createDocument($documentName, $project, $user);
$send = false;
$DDBBLangs = null;
$state = "ready";
list($encontrado, $matches) = $this->utiltranslate->encontrarOriginal($categoryName);
//$encontrado = $this->utiltranslate->findOriginal($originalText);
if ($encontrado) //Si el orgininal está registrado
{
//Obtiene las traducciones si están traducidas. Si no, devuelve -1 o -2.
$translation = $this->utiltranslate->getTranslation(
$categoryName,
$lang,
$encontrado,
$matches,
$document
);
//Si falta por crear la traducción la añadimos al original.
if ($translation === -3) {
$this->utiltranslate->createDictionary(
$categoryName,
"WebCategories",
$categoryName,
array($lang),
$project,
$document,
$user
);
$send = true;
$state = "pending";
$this->utiltranslate->sendNewTranslations(array($lang));
echo "El original es: " . $categoryName . " (EN -3)<br/>";
} else if ($translation === -2) {
$state = "pending";
echo "El original es: " . $categoryName . ". Estado: " . $translation . "<br>";
}
//echo "La traducción ".$translation." <br>";
//Marcamos la respuesta con el color correspondiente
$translation = $this->requestTranslation->manageTranslation($categoryName, $translation);
$response = $translation;
} else {
//si el original no existe, lo tenemos que crear y mandamos la respuesta vacia.
$send = true;
$state = "pending";
echo "Creamos el original (" . $categoryName . ") <br>";
//Función para crear el original y la traducción en TODOS los idiomas.
$this->utiltranslate->createDictionary(
$categoryName,
"WebCategories",
$categoryName,
$DDBBLangs,
$project,
$document,
$user
);
$error = $this->requestTranslation->marcarError($categoryName);
$response = $error;
$this->utiltranslate->sendNewTranslations($DDBBLangs);
}
} else { // Si el texto enviado está vacío no se hace nada.
$response = "El POST no contiene mensaje";
$state = "pending";
}
$fullResponse["response"] = $response;
$fullResponse["state"] = $state;
return $fullResponse;
}
private function sendResponse($response, $countryCode = "ES")
{
if ($countryCode == "ES") {
$url = "localhost/es?option=com_sync&task=syncTranslations.receiveResponse";
} else {
$url = "localhost/es?option=com_sync&task=syncTranslations.receiveResponse";
}
$ch = curl_init($url);
# Setup request to send json via POST.
curl_setopt($ch, CURLOPT_POSTFIELDS, $response);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
//Añadido para no tener problema con el certificado propio
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
# Return response instead of printing.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
# Send request.
$result = curl_exec($ch);
curl_close($ch);
//var_dump($result);
return $result;
}
private function cleanArray($array)
{
foreach ($array as $key => $element) {
if (strpos($element, "class='errorDiv'") !== false) {
unset($array[$key]);
} else $array[$key] = strip_tags($element);
}
return $array;
}
/**
* @Route("/translate/createEntities", name="createEntities")
*/
public function createEntitiesAction(){
list($data,$isArticle) = $this->getDataPostCreate();
if ($data["fullText"] !== "") {
$this->dispatchMessage(new Notify($data,$isArticle));
}
return $this->redirectToRoute('showTranslate');
}
/**
* @Route("/translate/file", name="translateFile")
*/
public function translateFile(Request $request){
$authKey = "62beb388-21eb-bd33-2106-853293519c50";
$translator = new \DeepL\Translator($authKey);
$langMapping = array("ES"=>"ES","PT"=>"PT-PT","EN"=>"EN-GB","FR"=>"FR","DE"=>"DE","IT"=>"IT", "NL"=>"NL");
$lang= $langMapping[$request->get('lang')];
$tmpRoot = $this->getParameter('kernel.project_dir') .'/src/tmp/';
$requestFile = $request->files->get('document');
$fullFileName = $requestFile->getClientOriginalName();
list($fromFileName, $fileExtension)=$this->splitExtension($fullFileName);
$fromFilePath = $tmpRoot.$fullFileName;
$fromFileName = new UnicodeString($fromFileName);
$toFileName = $fromFileName->ascii() ."_".$lang.".".$fileExtension;
$toFilePath = $tmpRoot. $toFileName;
if (file_exists($toFilePath)) {
unlink($toFilePath);
}
rename($requestFile,$fromFilePath);
try {
$translator->translateDocument(
$fromFilePath,
$toFilePath ,null,
$lang
);
$response = new BinaryFileResponse($toFilePath);
$disposition = HeaderUtils::makeDisposition(
HeaderUtils::DISPOSITION_ATTACHMENT,
$toFileName
);
$response->headers->set('Content-Disposition', $disposition);
} catch (\DeepL\DocumentTranslationException $error) {
$response = new response ('Error occurred while translating document: ' . ($error->getMessage() ?? 'unknown error'));
}
return $response;
}
private function splitExtension($file){
$splitFile=explode(".",$file);
$lastIndex=count($splitFile)-1;
$fileExtension = $splitFile[$lastIndex];
unset($splitFile[$lastIndex]);
$fileName = implode(".",$splitFile);
return array($fileName,$fileExtension);
}
}