From 0bce4a74f1e5e38e814b6729b97b540c600e7048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 1 Jun 2023 10:05:34 -0300 Subject: [PATCH 01/47] Remove unused --- .../Process/ProcessTranslationController.php | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Process/ProcessTranslationController.php b/ProcessMaker/Http/Controllers/Process/ProcessTranslationController.php index 79374c42e3..51fc48066d 100644 --- a/ProcessMaker/Http/Controllers/Process/ProcessTranslationController.php +++ b/ProcessMaker/Http/Controllers/Process/ProcessTranslationController.php @@ -24,39 +24,8 @@ public function export(Process $process, $languageCode) return view('processes.translations.export', compact('process', 'language')); } - /** - * Get page import - * - * @param Screen $screen - * - * @return Factory|View - */ public function import(Screen $screen) { return view('processes.translations.import'); } - - /** - * Download the JSON definition of the screen - * - * @param Screen $screen - * @param string $key - * - * @return stream - */ - public function download($processId, $language) - { - $fileName = trim($screen->title) . '.json'; - $fileContents = Cache::get($key); - - if (!$fileContents) { - return abort(404); - } else { - return response()->streamDownload(function () use ($fileContents) { - echo $fileContents; - }, $fileName, [ - 'Content-type' => 'application/json', - ]); - } - } } From a358c61eed8b5425d3546d468516d235e99085fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:33:03 -0300 Subject: [PATCH 02/47] Add preimport and import endpoints --- .../Api/ProcessTranslationController.php | 70 ++++++++++++++++--- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/ProcessTranslationController.php b/ProcessMaker/Http/Controllers/Api/ProcessTranslationController.php index 15b536b77e..6e99540ea7 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessTranslationController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessTranslationController.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Bus; +use function PHPUnit\Framework\isEmpty; use ProcessMaker\Http\Controllers\Controller; use ProcessMaker\Models\Process; use ProcessMaker\Models\ProcessTranslationToken; @@ -132,20 +133,71 @@ public function update(Request $request) $processTranslation->updateTranslations($screensTranslations, $language); } - public function export(Request $request, $processId, $language) + public function export(Request $request, $processId, $languageCode) { $process = Process::findOrFail($processId); $processTranslation = new ProcessTranslation($process); - $exportList = $processTranslation->exportTranslations($language); + $exportList = $processTranslation->exportTranslations($languageCode); - $fileName = trim($process->name) . '.json'; + $fileName = trim($process->name); - $fileContents = file_put_contents($fileName, json_encode($exportList)); - - return response()->streamDownload(function () use ($fileContents) { - echo $fileContents; - }, $fileName, [ - 'Content-type' => 'application/json', + $exportInfo = json_encode([ + 'processName' => $process->name, + 'language' => $languageCode, + 'humanLanguage' => Languages::ALL[$languageCode], ]); + + return response()->streamDownload( + function () use ($exportList) { + echo json_encode($exportList); + }, + $fileName . '.json', + [ + 'Content-type' => 'application/json', + 'export-info' => $exportInfo, + ] + ); + } + + public function preimportValidation(Request $request, $processId) + { + $content = $request->file('file')->get(); + $payload = json_decode($content, true); + + $process = Process::findOrFail($processId); + $processTranslation = new ProcessTranslation($process); + $importData = $processTranslation->getImportData($payload); + + if (!$importData || !count($importData)) { + return response( + ['message' => __('Please verify that the file contains translations for this process.')], + 422 + ); + } + + return [ + 'importData' => $importData, + ]; + } + + public function import(Request $request, $processId) + { + $content = $request->file('file')->get(); + $payload = json_decode($content, true); + + $process = Process::findOrFail($processId); + $processTranslation = new ProcessTranslation($process); + $importData = $processTranslation->importTranslations($payload); + + if (!$importData || !count($importData)) { + return response( + ['message' => __('Please verify that the file contains translations for this process.')], + 422 + ); + } + + return [ + 'importData' => $importData, + ]; } } From 3ace7e945cfc1cfca5a0b23d4e7dee2c8bff2526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:33:28 -0300 Subject: [PATCH 03/47] Add import method in controller to show view --- .../Http/Controllers/Process/ProcessTranslationController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Process/ProcessTranslationController.php b/ProcessMaker/Http/Controllers/Process/ProcessTranslationController.php index 51fc48066d..53dd76a138 100644 --- a/ProcessMaker/Http/Controllers/Process/ProcessTranslationController.php +++ b/ProcessMaker/Http/Controllers/Process/ProcessTranslationController.php @@ -24,8 +24,8 @@ public function export(Process $process, $languageCode) return view('processes.translations.export', compact('process', 'language')); } - public function import(Screen $screen) + public function import(Process $process) { - return view('processes.translations.import'); + return view('processes.translations.import', compact('process')); } } From b6a544516f96b1427a173304fedec9f1a39b2733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:34:00 -0300 Subject: [PATCH 04/47] Add get import data and import methods --- .../ProcessTranslation.php | 95 ++++++++++++++++++- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/ProcessMaker/ProcessTranslations/ProcessTranslation.php b/ProcessMaker/ProcessTranslations/ProcessTranslation.php index a408e51805..463b8bbd5b 100644 --- a/ProcessMaker/ProcessTranslations/ProcessTranslation.php +++ b/ProcessMaker/ProcessTranslations/ProcessTranslation.php @@ -372,11 +372,11 @@ public function deleteTranslations($language) if ($processTranslationToken) { $token = $processTranslationToken->token; $processTranslationToken->delete(); - } - // Cancel pending batch jobs - $batch = Bus::findBatch($token); - $batch->cancel(); + // Cancel pending batch jobs + $batch = Bus::findBatch($token); + $batch->cancel(); + } return true; } @@ -415,6 +415,9 @@ public function exportTranslations($language) $translations = null; $exportList = []; foreach ($screensTranslations as $screenTranslation) { + $screen = Screen::findOrFail($screenTranslation['id']); + $uuid = $screen->uuid; + $availableStrings = $screenTranslation['availableStrings']; if ($screenTranslation['translations']) { @@ -430,11 +433,93 @@ public function exportTranslations($language) } } } - $exportList[$screenTranslation['id']][$language][] = $translation; + $exportList[$uuid][$language][] = $translation; } } // Generate json file to export return $exportList; } + + public function getImportData($payload) + { + $screens = []; + foreach ($payload as $screenId => $value) { + $languages = []; + $screen = Screen::where('uuid', $screenId)->first(); + if ($screen) { + foreach ($value as $languageCode => $translations) { + $languages[] = [ + 'language' => $languageCode, + 'languageHuman' => Languages::ALL[$languageCode], + ]; + } + $screens[] = [ + 'id' => $screen->id, + 'uuid' => $screenId, + 'title' => $screen->title, + 'languages' => $languages, + ]; + } + } + + // Group by language + $languageGrouped = []; + foreach ($screens as $uuid => $value) { + foreach ($value['languages'] as $key => $translations) { + $languageGrouped[$translations['language']]['languageHuman'] = $translations['languageHuman']; + $languageGrouped[$translations['language']]['screens'][$value['uuid']] = $value['title']; + } + } + + return $languageGrouped; + } + + public function importTranslations($payload) + { + $screens = []; + foreach ($payload as $screenUuid => $value) { + $screen = Screen::where('uuid', $screenUuid)->first(); + if ($screen) { + $screenTranslations = $screen->translations; + $availableStrings = $this->getStringsInScreen($screen); + + foreach ($value as $languageCode => $translations) { + if (!array_key_exists($languageCode, $screenTranslations)) { + $screenTranslations[$languageCode]['strings'] = []; + } + + foreach ($translations as $importedTranslation) { + // $found = false; + foreach ($availableStrings as $availableString) { + if ($availableString === $importedTranslation['key']) { + } + } + foreach ($screenTranslations[$languageCode]['strings'] as &$translation) { + if ($translation['key'] === $importedTranslation['key']) { + $translation['string'] = $importedTranslation['string']; + // $found = true; + } + } + + /** + * Should only add for the elements in the screens. If there are some translation in the file + * for a field that does not exist in the screen should not add it. I.E. If we don't have the field + * "First name" in the screen but we have a key "First name" in the importing file, should not add + * the translation + * */ + // if (!$found) { + // $screenTranslations[$languageCode]['strings'][] = [ + // 'key' => $importedTranslation['key'], + // 'string' => $importedTranslation['string'], + // ]; + // } + } + } + } + dd($screenTranslations); + } + + dd($screenTranslations); + } } From da2336c3c537dd0befcd9215474f6de580f47be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:34:28 -0300 Subject: [PATCH 05/47] Add ui for import --- resources/js/processes/translations/import.js | 3 + resources/views/processes/edit.blade.php | 4 +- .../processes/translations/import.blade.php | 201 +++++++++++------- webpack.mix.js | 2 + 4 files changed, 135 insertions(+), 75 deletions(-) create mode 100644 resources/js/processes/translations/import.js diff --git a/resources/js/processes/translations/import.js b/resources/js/processes/translations/import.js new file mode 100644 index 0000000000..f713d93a64 --- /dev/null +++ b/resources/js/processes/translations/import.js @@ -0,0 +1,3 @@ +import DraggableFileUpload from '../../components/shared/DraggableFileUpload'; + +Vue.component("DraggableFileUpload", DraggableFileUpload); diff --git a/resources/views/processes/edit.blade.php b/resources/views/processes/edit.blade.php index eb56f0daca..1e4f5ca201 100644 --- a/resources/views/processes/edit.blade.php +++ b/resources/views/processes/edit.blade.php @@ -188,7 +188,7 @@ @canany(['import-process-translation', 'create-process-translation'])
- @can('import-process-templates') + @can('import-process-translation')
{{__('Import')}} @@ -501,7 +501,7 @@ class="custom-control-input"> this.$bvModal.show("createProcessTranslation"); }, importTranslation() { - + window.location = `/processes/${this.formData.id}/import/translation` }, } }); diff --git a/resources/views/processes/translations/import.blade.php b/resources/views/processes/translations/import.blade.php index 8d75c87845..cdf18e419c 100644 --- a/resources/views/processes/translations/import.blade.php +++ b/resources/views/processes/translations/import.blade.php @@ -16,110 +16,165 @@ ]]) @endsection @section('content') -
-
-
-
-
-
{{__('Import Screen')}}
-
-
-
{{__('You are about to import a Screen.')}}
- - -
- -
-
-
- - -
    -
  • - - @{{item.label}} - @{{item.message}} - @{{item.info}}. -
  • -
-
- -
-
- -
+
+
+
+
+
+
Import Process Translation
+ Import a Process Translation into process {{ $process->name }} for this ProcessMaker environment +
+
+
+ +
+
You are about to import the following translations for the process {{$process->name}}:
+
+ @{{file.name}} + + + +
+
+
+
@{{ key.toUpperCase() + ' - ' + language.languageHuman }}
+
  • @{{ screen }}
  • +
    +
    +
    +
    +
    + +
    +
    +
    +
    @endsection @section('js') + + + @endsection diff --git a/webpack.mix.js b/webpack.mix.js index 804bc806bf..c897cd7f06 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -105,6 +105,8 @@ mix.js("resources/js/app-layout.js", "public/js") .js("resources/js/requests/show.js", "public/js/requests") .js("resources/js/requests/preview.js", "public/js/requests") + .js("resources/js/processes/translations/import.js", "public/js/processes/translations") + .js("resources/js/tasks/index.js", "public/js/tasks/index.js") .js("resources/js/tasks/show.js", "public/js/tasks/show.js") From 0152acf7b3404b2e09f1ae57090897b3f39febef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:34:47 -0300 Subject: [PATCH 06/47] Fix download export file --- .../views/processes/translations/export.blade.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/resources/views/processes/translations/export.blade.php b/resources/views/processes/translations/export.blade.php index 9a7b44c9f9..5d03bf77e7 100644 --- a/resources/views/processes/translations/export.blade.php +++ b/resources/views/processes/translations/export.blade.php @@ -54,7 +54,7 @@ }, methods: { onCancel() { - window.location = '{{ route("processes.index") }}'; + window.location = `/processes/${this.processId}/edit`; }, onExport() { ProcessMaker.apiClient({ @@ -63,18 +63,15 @@ responseType: 'blob', data: {} }).then(response => { - console.log(response); - // const exportInfo = JSON.parse(response.headers['fileName']); - const url = window.URL.createObjectURL(new Blob([response])); + const exportInfo = JSON.parse(response.headers['export-info']); + const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement("a"); link.href = url; - // link.setAttribute("download", `${exportInfo.name.replace(' ', '_')}.json`); - link.setAttribute("download", `translations.json`); + link.setAttribute("download", `${exportInfo.processName.replaceAll(' ', '_')}-${exportInfo.language.toUpperCase()}.json`); document.body.appendChild(link); link.click(); - // ProcessMaker.alert(`The translation ${exportInfo.name} was exported`, 'success'); - ProcessMaker.alert(`The translation was exported`, 'success'); + ProcessMaker.alert(`The translation ${exportInfo.humanLanguage} for the process ${exportInfo.processName} was exported`, 'success'); }); }, } From 92874b256edcf5c59f9a2f71bc63b5239c9418b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:34:52 -0300 Subject: [PATCH 07/47] Add routes --- routes/api.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/routes/api.php b/routes/api.php index d3e46b0bbe..78fd639659 100644 --- a/routes/api.php +++ b/routes/api.php @@ -255,6 +255,8 @@ Route::get('process/translations/{processId}', [ProcessTranslationController::class, 'show'])->name('process-translation.show'); //->middleware('translation-authorization'); Route::delete('process/translations/{processId}/{language}', [ProcessTranslationController::class, 'delete'])->name('process-translation.delete'); //->middleware('translation-authorization'); Route::post('processes/{processId}/export/translation/{language}', [ProcessTranslationController::class, 'export'])->name('process-translation.export'); //->middleware('translation-authorization'); + Route::post('processes/{processId}/import/translation/validation', [ProcessTranslationController::class, 'preimportValidation'])->name('process-translation.preImport'); //->middleware('translation-authorization'); + Route::post('processes/{processId}/import/translation', [ProcessTranslationController::class, 'import'])->name('process-translation.import'); //->middleware('translation-authorization'); // debugging javascript errors Route::post('debug', [DebugController::class, 'store'])->name('debug.store')->middleware('throttle'); From 689c340efee98fc4dabe29bb1178269928666431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Fri, 2 Jun 2023 12:24:06 -0300 Subject: [PATCH 08/47] Add code in endpoint to perform import --- .../Api/ProcessTranslationController.php | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/ProcessTranslationController.php b/ProcessMaker/Http/Controllers/Api/ProcessTranslationController.php index 6e99540ea7..ccd3044255 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessTranslationController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessTranslationController.php @@ -187,17 +187,8 @@ public function import(Request $request, $processId) $process = Process::findOrFail($processId); $processTranslation = new ProcessTranslation($process); - $importData = $processTranslation->importTranslations($payload); + $processTranslation->importTranslations($payload); - if (!$importData || !count($importData)) { - return response( - ['message' => __('Please verify that the file contains translations for this process.')], - 422 - ); - } - - return [ - 'importData' => $importData, - ]; + return response()->json(['processId' => $processId], 200); } } From fcd55ce933d40f0d97db796740efbfbe30edab53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Fri, 2 Jun 2023 12:24:33 -0300 Subject: [PATCH 09/47] Add logic to handle import --- .../ProcessTranslation.php | 77 +++++++++++++------ 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/ProcessMaker/ProcessTranslations/ProcessTranslation.php b/ProcessMaker/ProcessTranslations/ProcessTranslation.php index 463b8bbd5b..0ae3210f43 100644 --- a/ProcessMaker/ProcessTranslations/ProcessTranslation.php +++ b/ProcessMaker/ProcessTranslations/ProcessTranslation.php @@ -480,6 +480,7 @@ public function importTranslations($payload) $screens = []; foreach ($payload as $screenUuid => $value) { $screen = Screen::where('uuid', $screenUuid)->first(); + $newScreenTranslations = []; if ($screen) { $screenTranslations = $screen->translations; $availableStrings = $this->getStringsInScreen($screen); @@ -489,37 +490,67 @@ public function importTranslations($payload) $screenTranslations[$languageCode]['strings'] = []; } - foreach ($translations as $importedTranslation) { - // $found = false; - foreach ($availableStrings as $availableString) { - if ($availableString === $importedTranslation['key']) { + $newTranslations = []; + // For each of the available elements in the screens + foreach ($availableStrings as $availableString) { + // We need to check if there are current translations in the translation + // column (old translations) for that available string + $foundOld = false; + foreach ($screenTranslations[$languageCode]['strings'] as $inDbTranslation) { + if ($availableString === $inDbTranslation['key']) { + $foundOld = true; + $oldTranslation = [ + 'key' => $inDbTranslation['key'], + 'string' => $inDbTranslation['string'], + ]; } } - foreach ($screenTranslations[$languageCode]['strings'] as &$translation) { - if ($translation['key'] === $importedTranslation['key']) { - $translation['string'] = $importedTranslation['string']; - // $found = true; + + // We need to check if there are some translation in the translation file + // for that available string + $foundInFile = false; + foreach ($translations as $importedTranslation) { + if ($availableString === $importedTranslation['key']) { + $foundInFile = true; + $inFileTranslation = [ + 'key' => $importedTranslation['key'], + 'string' => $importedTranslation['string'], + ]; } } - /** - * Should only add for the elements in the screens. If there are some translation in the file - * for a field that does not exist in the screen should not add it. I.E. If we don't have the field - * "First name" in the screen but we have a key "First name" in the importing file, should not add - * the translation - * */ - // if (!$found) { - // $screenTranslations[$languageCode]['strings'][] = [ - // 'key' => $importedTranslation['key'], - // 'string' => $importedTranslation['string'], - // ]; - // } + if ($foundOld && !$foundInFile) { + $newTranslations[] = $oldTranslation; + } + + if (!$foundOld && $foundInFile) { + $newTranslations[] = $inFileTranslation; + } + + if ($foundOld && $foundInFile && $inFileTranslation['string'] === '') { + $newTranslations[] = $inFileTranslation; + } + + if ($foundOld && $foundInFile && $inFileTranslation['string'] === null) { + $newTranslations[] = $oldTranslation; + } + + if ($foundOld && $foundInFile && $inFileTranslation['string'] && $inFileTranslation['string'] !== '') { + $newTranslations[] = $inFileTranslation; + } + } + + // Assign new translations to language in screen + // $newScreenTranslations[$languageCode]['strings'] = $newTranslations; + foreach ($screenTranslations as $language => $translations) { + if ($language === $languageCode) { + $screenTranslations[$languageCode]['strings'] = $newTranslations; + } } } + $screen->translations = $screenTranslations; + $screen->save(); } - dd($screenTranslations); } - - dd($screenTranslations); } } From 9e8e492419e6876ff6a6cad5a48247fbf51e8a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Fri, 2 Jun 2023 12:24:53 -0300 Subject: [PATCH 10/47] Fix routes in breadcrumb --- resources/views/processes/translations/export.blade.php | 1 + resources/views/processes/translations/import.blade.php | 5 +++-- routes/web.php | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/resources/views/processes/translations/export.blade.php b/resources/views/processes/translations/export.blade.php index 5d03bf77e7..9100d5d979 100644 --- a/resources/views/processes/translations/export.blade.php +++ b/resources/views/processes/translations/export.blade.php @@ -12,6 +12,7 @@ @include('shared.breadcrumbs', ['routes' => [ __('Designer') => route('processes.index'), __('Processes') => route('processes.index'), + __('Translations') => route('processes.edit', ['process' => $process->id]), __('Export' . ' ' . $process->name . ' - ' . $language['humanLanguage']) => null, ]]) @endsection diff --git a/resources/views/processes/translations/import.blade.php b/resources/views/processes/translations/import.blade.php index cdf18e419c..5ce91086ca 100644 --- a/resources/views/processes/translations/import.blade.php +++ b/resources/views/processes/translations/import.blade.php @@ -11,8 +11,9 @@ @section('breadcrumbs') @include('shared.breadcrumbs', ['routes' => [ __('Designer') => route('processes.index'), - __('Screens') => route('screens.index'), - __('Import') => null, + __('Processes') => route('processes.index'), + __('Translations') => route('processes.edit', ['process' => $process->id]), + __('Import') => null, ]]) @endsection @section('content') diff --git a/routes/web.php b/routes/web.php index 57684d5b7d..97223cc93e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -90,7 +90,7 @@ Route::get('processes/create', [ProcessController::class, 'create'])->name('processes.create')->middleware('can:create-processes'); Route::post('processes', [ProcessController::class, 'store'])->name('processes.store')->middleware('can:edit-processes'); Route::get('processes/{process}', [ProcessController::class, 'show'])->name('processes.show')->middleware('can:view-processes'); - Route::put('processes/{process}', [ProcessController::class, 'update'])->name('processes.edit')->middleware('can:edit-processes'); + Route::put('processes/{process}', [ProcessController::class, 'update'])->name('processes.update')->middleware('can:edit-processes'); Route::delete('processes/{process}', [ProcessController::class, 'destroy'])->name('processes.destroy')->middleware('can:archive-processes'); Route::get('processes/{process}/export/translation/{language}', [ProcessTranslationController::class, 'export']); From 2d101f2138d506fbbd3ab5316faa37b433345c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Fri, 2 Jun 2023 15:04:03 -0300 Subject: [PATCH 11/47] Apply translations to web entries --- ProcessMaker/Http/Resources/ScreenVersion.php | 15 +- ProcessMaker/Http/Resources/Task.php | 4 +- .../ProcessTranslations/ScreenTranslation.php | 211 ++++++++++++++++++ .../components/ProcessTranslationListing.vue | 5 +- 4 files changed, 228 insertions(+), 7 deletions(-) create mode 100644 ProcessMaker/ProcessTranslations/ScreenTranslation.php diff --git a/ProcessMaker/Http/Resources/ScreenVersion.php b/ProcessMaker/Http/Resources/ScreenVersion.php index 96bbe3e443..751191b274 100644 --- a/ProcessMaker/Http/Resources/ScreenVersion.php +++ b/ProcessMaker/Http/Resources/ScreenVersion.php @@ -2,8 +2,10 @@ namespace ProcessMaker\Http\Resources; -use ProcessMaker\Models\ProcessRequestToken; +use ProcessMaker\Models\Process; use ProcessMaker\Models\Screen; +use ProcessMaker\ProcessTranslations\ProcessTranslation; +use ProcessMaker\ProcessTranslations\ScreenTranslation; class ScreenVersion extends ApiResource { @@ -34,6 +36,17 @@ public function toArray($request) $screenVersion['nested'] = $nested; } + // If web entry, apply translations + if (!$task) { + // Apply translations to screen + $screenTranslation = new ScreenTranslation($screenVersion); + $screenVersion['config'] = $screenTranslation->applyTranslations($screenVersion); + // Apply translations to nested screens + foreach ($screenVersion['nested'] as &$nestedScreen) { + $nestedScreen['config'] = $screenTranslation->applyTranslations($nestedScreen); + } + } + return $screenVersion; } } diff --git a/ProcessMaker/Http/Resources/Task.php b/ProcessMaker/Http/Resources/Task.php index f8cc2762f6..0f8e9e8184 100644 --- a/ProcessMaker/Http/Resources/Task.php +++ b/ProcessMaker/Http/Resources/Task.php @@ -66,11 +66,11 @@ public function toArray($request) // Apply translations to screen $process = Process::findOrFail($this->processRequest->process_id); $processTranslation = new ProcessTranslation($process); - $array['screen']['config'] = $processTranslation->applyTranslations($array['screen'], $this->processRequest->process_id); + $array['screen']['config'] = $processTranslation->applyTranslations($array['screen']); // Apply translations to nested screens foreach ($array['screen']['nested'] as &$nestedScreen) { - $nestedScreen['config'] = $processTranslation->applyTranslations($nestedScreen, $this->processRequest->process_id); + $nestedScreen['config'] = $processTranslation->applyTranslations($nestedScreen); } } diff --git a/ProcessMaker/ProcessTranslations/ScreenTranslation.php b/ProcessMaker/ProcessTranslations/ScreenTranslation.php new file mode 100644 index 0000000000..212e549dc0 --- /dev/null +++ b/ProcessMaker/ProcessTranslations/ScreenTranslation.php @@ -0,0 +1,211 @@ +screen = $screen; + } + + public function getStrings($screen) : SupportCollection + { + $screen['availableStrings'] = $this->getStringsInScreen($screen); + unset($screen['config']); + + return collect($screen); + } + + private function getStringsInScreen($screen) + { + $strings = []; + if (!$screen) { + return $strings; + } + + $config = $screen['config']; + + if ($config) { + foreach ($config as $page) { + if (isset($page['items']) && is_array($page['items'])) { + $strings = array_merge($strings, self::getStringElements($page['items'])); + } + } + } + + return $strings; + } + + private static function getStringElements($items, $parent = null) + { + $elements = []; + + foreach ($items as $item) { + if (isset($item['items']) && is_array($item['items'])) { + // If have items and is a loop .. + if ($item['component'] == 'FormLoop') { + $elements = array_merge($elements, self::getStringElements($item['items'])); + } + // If have items and is a table .. + if ($item['component'] == 'FormMultiColumn') { + foreach ($item['items'] as $cell) { + if (is_array($cell)) { + $elements = array_merge($elements, self::getStringElements($cell)); + } + } + } + } else { + if (!isset($item['component'])) { + continue; + } + + if ($item['component'] === 'FormNestedScreen') { + continue; + } + + if ($item['component'] === 'FormImage') { + continue; + } + + // Specific for Rich text + if ($item['component'] === 'FormHtmlViewer') { + $elements[] = $item['config']['content']; + } + + // Specific for Select list + if ($item['component'] === 'FormSelectList') { + if (isset($item['config']) && isset($item['config']['options']) && isset($item['config']['options']['optionsList'])) { + foreach ($item['config']['options']['optionsList'] as $option) { + $elements[] = $option['content']; + } + } + } + + // Look for label strings + if (isset($item['config']) && isset($item['config']['label'])) { + $elements[] = $item['config']['label']; + } + + // Look for helper strings + if (isset($item['config']) && isset($item['config']['helper'])) { + $elements[] = $item['config']['helper']; + } + + // Look for placeholder strings + if (isset($item['config']) && isset($item['config']['placeholder'])) { + $elements[] = $item['config']['placeholder']; + } + } + } + + return $elements; + } + + public function applyTranslations($screen) + { + $config = $screen['config']; + $translations = $screen['translations']; + $targetLanguage = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); + $targetLanguage = array_key_exists($targetLanguage, Languages::ALL) ? $targetLanguage : 'en'; + + if (!Auth::user()->isAnonymous) { + $targetLanguage = Auth::user()->language; + } + + if (!$translations) { + return $config; + } + + if (array_key_exists($targetLanguage, $translations)) { + foreach ($translations[$targetLanguage]['strings'] as $translation) { + $this->applyTranslationsToScreen($translation['key'], $translation['string'], $config); + } + } + + return $config; + } + + public function applyTranslationsToScreen($key, $translatedString, &$config) + { + if ($config) { + foreach ($config as &$page) { + if (isset($page['items']) && is_array($page['items'])) { + $replaced = self::applyTranslationToElement($page['items'], $key, $translatedString); + } + } + } + + return $config; + } + + private static function applyTranslationToElement(&$items, $key, $translatedString) + { + foreach ($items as &$item) { + if (isset($item['items']) && is_array($item['items'])) { + // If have items and is a loop .. + if ($item['component'] == 'FormLoop') { + $replaced = self::applyTranslationToElement($item['items'], $key, $translatedString); + } + // If have items and is a table .. + if ($item['component'] == 'FormMultiColumn') { + foreach ($item['items'] as &$cell) { + if (is_array($cell)) { + $replaced = self::applyTranslationToElement($cell, $key, $translatedString); + } + } + } + } else { + if (!isset($item['component'])) { + continue; + } + + if ($item['component'] === 'FormNestedScreen') { + continue; + } + + if ($item['component'] === 'FormImage') { + continue; + } + + // Specific for Rich text + if ($item['component'] === 'FormHtmlViewer' && $item['config']['content'] === $key) { + $item['config']['content'] = $translatedString; + } + + // Specific for Select list + if ($item['component'] === 'FormSelectList') { + if (isset($item['config']) && isset($item['config']['options']) && isset($item['config']['options']['optionsList'])) { + foreach ($item['config']['options']['optionsList'] as $option) { + if ($option['content'] === $key) { + $option['content'] = $translatedString; + } + } + } + } + + // Look for label strings + if (isset($item['config']) && isset($item['config']['label']) && $item['config']['label'] === $key) { + $item['config']['label'] = $translatedString; + } + + // Look for helper strings + if (isset($item['config']) && isset($item['config']['helper']) && $item['config']['helper'] === $key) { + $item['config']['helper'] = $translatedString; + } + + // Look for placeholder strings + if (isset($item['config']) && isset($item['config']['placeholder']) && $item['config']['placeholder'] === $key) { + $item['config']['placeholder'] = $translatedString; + } + } + } + + return $items; + } +} diff --git a/resources/js/processes/translations/components/ProcessTranslationListing.vue b/resources/js/processes/translations/components/ProcessTranslationListing.vue index fa922cc2e2..5771515232 100644 --- a/resources/js/processes/translations/components/ProcessTranslationListing.vue +++ b/resources/js/processes/translations/components/ProcessTranslationListing.vue @@ -46,7 +46,7 @@ :actions="actions" :permission="permission" :data="item" - :divider="true" + :divider="false" @navigate="onNavigate" /> @@ -105,9 +105,6 @@ export default { }, ], actionsInProgress: [ - { - value: "retry-translation", content: "Retry Translation", link: false, href: "", permission: "edit-process-translation", icon: "fas fa-redo", - }, { value: "delete-translation", content: "Delete Translation", permission: "delete-process-translation", icon: "fas fa-trash", }, From c886fb8540983c3bb138fae179f55e5bb89a423f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Fri, 2 Jun 2023 16:25:11 -0300 Subject: [PATCH 12/47] Add screen title translations --- .../ScreenTitleLanguageTranslationHandler.php | 86 ++++++++++++++++++ .../language_translation_screen_title.md | 8 ++ .../ExecuteScreenTitleTranslationRequest.php | 88 +++++++++++++++++++ .../Jobs/ExecuteTranslationRequest.php | 6 ++ .../ProcessTranslations/BatchesJobHandler.php | 19 +++- .../ProcessTranslation.php | 7 ++ .../CreateProcessTranslationModal.vue | 30 ++++--- 7 files changed, 233 insertions(+), 11 deletions(-) create mode 100644 ProcessMaker/Ai/Handlers/ScreenTitleLanguageTranslationHandler.php create mode 100644 ProcessMaker/Ai/Prompts/language_translation_screen_title.md create mode 100644 ProcessMaker/Jobs/ExecuteScreenTitleTranslationRequest.php diff --git a/ProcessMaker/Ai/Handlers/ScreenTitleLanguageTranslationHandler.php b/ProcessMaker/Ai/Handlers/ScreenTitleLanguageTranslationHandler.php new file mode 100644 index 0000000000..c643132676 --- /dev/null +++ b/ProcessMaker/Ai/Handlers/ScreenTitleLanguageTranslationHandler.php @@ -0,0 +1,86 @@ +config = [ + 'model' => 'text-davinci-003', + 'max_tokens' => 500, + 'temperature' => 0, + 'top_p' => 1, + 'n' => 1, + 'frequency_penalty' => 0, + 'presence_penalty' => 0, + 'stop' => 'END_', + ]; + } + + public function setTargetLanguage($language) + { + $this->targetLanguage = $language; + } + + public function getPromptFile($type = null) + { + return file_get_contents($this->getPromptsPath() . 'language_translation_' . $type . '.md'); + } + + public function generatePrompt(String $type = null, String $string) : Object + { + $prompt = $this->getPromptFile($type); + $prompt = $this->replaceString($prompt, $string); + $prompt = $this->replaceLanguage($prompt, $this->targetLanguage); + $prompt = $this->replaceStopSequence($prompt); + $this->config['prompt'] = $prompt; + + return $this; + } + + public function execute() + { + $client = app(Client::class); + $response = $client + ->completions() + ->create(array_merge($this->getConfig())); + + return $this->formatResponse($response); + } + + private function formatResponse($response) + { + $result = ltrim($response->choices[0]->text); + $result = rtrim(rtrim(str_replace("\n", '', $result))); + $result = str_replace('\'', '', $result); + + return [$result, $response->usage, $this->question]; + } + + public function replaceStopSequence($prompt) + { + $replaced = str_replace('{stopSequence}', $this->config['stop'] . " \n", $prompt); + + return $replaced; + } + + public function replaceString($prompt, $json_list) + { + $replaced = str_replace('{replaceString}', $json_list . " \n", $prompt); + + return $replaced; + } + + public function replaceLanguage($prompt, $language) + { + $replaced = str_replace('{language}', $language . " \n", $prompt); + + return $replaced; + } +} diff --git a/ProcessMaker/Ai/Prompts/language_translation_screen_title.md b/ProcessMaker/Ai/Prompts/language_translation_screen_title.md new file mode 100644 index 0000000000..5054847922 --- /dev/null +++ b/ProcessMaker/Ai/Prompts/language_translation_screen_title.md @@ -0,0 +1,8 @@ +You are an i18n-compatible translation service. You know how to do high quality human translations. Translate the strings within the JSON. Maintain whitespace. Do not modify or translate interpolated variables in any way. You are going to translate the strings in the following json to the language {language}. Respect capital letters. + + +{stopSequence} +Translate the following string: +{replaceString} +{stopSequence} +Response: \ No newline at end of file diff --git a/ProcessMaker/Jobs/ExecuteScreenTitleTranslationRequest.php b/ProcessMaker/Jobs/ExecuteScreenTitleTranslationRequest.php new file mode 100644 index 0000000000..490c05b473 --- /dev/null +++ b/ProcessMaker/Jobs/ExecuteScreenTitleTranslationRequest.php @@ -0,0 +1,88 @@ +screen = $screen; + $this->handler = $languageTranslationHandler; + $this->type = $type; + $this->targetLanguage = $targetLanguage; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + \Log::info('Calling OpenAI for screen title translation...'); + $this->handler->generatePrompt( + $this->type, + $this->screen['title'], + ); + + [$response, $usage, $targetLanguage] = $this->handler->execute(); + + $saved = $this->saveTranslationsInScreen($this->screen['id'], $response); + } + + private function saveTranslationsInScreen($screenId, $screenTitleTranslation) + { + if (!$screenTitleTranslation) { + return; + } + + $screen = Screen::findOrFail($screenId); + $screenTranslations = $screen->translations; + + if (!$screenTranslations || !array_key_exists($this->targetLanguage['language'], $screenTranslations)) { + $screenTranslations[$this->targetLanguage['language']]['screenTitle'] = []; + } + + $screenTranslations[$this->targetLanguage['language']]['screen_title'] = $screenTitleTranslation; + $screenTranslations[$this->targetLanguage['language']]['strings'] = []; + $screenTranslations[$this->targetLanguage['language']]['created_at'] = Carbon::now(); + $screenTranslations[$this->targetLanguage['language']]['updated_at'] = Carbon::now(); + + $screen->translations = $screenTranslations; + $screen->save(); + + \Log::info('Translation title saved OK.'); + } +} diff --git a/ProcessMaker/Jobs/ExecuteTranslationRequest.php b/ProcessMaker/Jobs/ExecuteTranslationRequest.php index 778f6450f6..e6dbb7ebad 100644 --- a/ProcessMaker/Jobs/ExecuteTranslationRequest.php +++ b/ProcessMaker/Jobs/ExecuteTranslationRequest.php @@ -80,6 +80,10 @@ private function saveTranslationsInScreen($screenId, $chunkResponse) $screenTranslations[$this->targetLanguage['language']]['strings'] = []; } + if (!array_key_exists('strings', $screenTranslations[$this->targetLanguage['language']])) { + $screenTranslations[$this->targetLanguage['language']]['strings'] = []; + } + $strings = $screenTranslations[$this->targetLanguage['language']]['strings']; // For each of the result chunkResponse translations of the screen foreach ($chunkResponse as $item) { @@ -98,7 +102,9 @@ private function saveTranslationsInScreen($screenId, $chunkResponse) } } + $translatedScreenTitle = $screenTranslations[$this->targetLanguage['language']]['screen_title']; $screenTranslations[$this->targetLanguage['language']]['strings'] = $strings; + $screenTranslations[$this->targetLanguage['language']]['screen_title'] = ($translatedScreenTitle && $translatedScreenTitle !== '' ? $translatedScreenTitle : ''); $screenTranslations[$this->targetLanguage['language']]['created_at'] = Carbon::now(); $screenTranslations[$this->targetLanguage['language']]['updated_at'] = Carbon::now(); diff --git a/ProcessMaker/ProcessTranslations/BatchesJobHandler.php b/ProcessMaker/ProcessTranslations/BatchesJobHandler.php index 8c93553fe3..743f774947 100644 --- a/ProcessMaker/ProcessTranslations/BatchesJobHandler.php +++ b/ProcessMaker/ProcessTranslations/BatchesJobHandler.php @@ -5,6 +5,8 @@ use Illuminate\Bus\Batch; use Illuminate\Support\Facades\Bus; use ProcessMaker\Ai\Handlers\LanguageTranslationHandler; +use ProcessMaker\Ai\Handlers\ScreenTitleLanguageTranslationHandler; +use ProcessMaker\Jobs\ExecuteScreenTitleTranslationRequest; use ProcessMaker\Jobs\ExecuteTranslationRequest; use ProcessMaker\Models\ProcessTranslationToken; use ProcessMaker\Models\User; @@ -47,12 +49,14 @@ public function __construct($process, $screens, $targetLanguage, $code, $user, $ */ public function handle() { + $screenTitleLanguageTranslationHandler = new ScreenTitleLanguageTranslationHandler(); + $screenTitleLanguageTranslationHandler->setTargetLanguage($this->targetLanguage['humanLanguage']); + $languageTranslationHandler = new LanguageTranslationHandler(); $languageTranslationHandler->setTargetLanguage($this->targetLanguage['humanLanguage']); [$screensWithChunks, $chunksCount] = $this->prepareData($this->screens, $languageTranslationHandler); // Execute requests for each regular chunk - $batch = Bus::batch([]) ->then(function (Batch $batch) { \Log::info('All jobs in batch completed'); @@ -79,6 +83,19 @@ public function handle() // Update with real batch token ... ProcessTranslationToken::where('token', $this->code)->update(['token' => $batch->id]); + // Translate screen titles + foreach ($this->screens as $screen) { + $batch->add( + new ExecuteScreenTitleTranslationRequest( + $screen, + $screenTitleLanguageTranslationHandler, + 'screen_title', + $this->targetLanguage + ) + ); + } + + // Translate screen strings chunks foreach ($screensWithChunks as $screenId => $screenWithChunks) { foreach ($screenWithChunks as $chunk) { $batch->add( diff --git a/ProcessMaker/ProcessTranslations/ProcessTranslation.php b/ProcessMaker/ProcessTranslations/ProcessTranslation.php index 0ae3210f43..6215187561 100644 --- a/ProcessMaker/ProcessTranslations/ProcessTranslation.php +++ b/ProcessMaker/ProcessTranslations/ProcessTranslation.php @@ -95,11 +95,17 @@ public function getTranslatedLanguageList($screensTranslations) foreach ($screenTranslation['translations'] as $key => $translation) { $createdAt = $translation['created_at']; $updatedAt = $translation['updated_at']; + $screenTitle = ''; + + if (array_key_exists('screen_title', $translation)) { + $screenTitle = $translation['screen_title']; + } // If updated is greater than existing in array, modify it with the newest if (array_key_exists($key, $languages)) { $createdAt = $languages[$key]['createdAt']; $updatedAt = $languages[$key]['updatedAt']; + $screenTitle = $languages[$key]['screen_title']; if ($languages[$key]['updatedAt'] < $translation['updated_at']) { $createdAt = $translation['created_at']; $updatedAt = $translation['updated_at']; @@ -112,6 +118,7 @@ public function getTranslatedLanguageList($screensTranslations) 'humanLanguage' => Languages::ALL[$key], 'createdAt' => $createdAt, 'updatedAt' => $updatedAt, + 'screen_title' => $screenTitle, ]; } } diff --git a/resources/js/processes/translations/components/CreateProcessTranslationModal.vue b/resources/js/processes/translations/components/CreateProcessTranslationModal.vue index 9f6fd6db1c..20f683f27c 100644 --- a/resources/js/processes/translations/components/CreateProcessTranslationModal.vue +++ b/resources/js/processes/translations/components/CreateProcessTranslationModal.vue @@ -56,17 +56,24 @@
    -
    - - - {{ $t("Select a screen from the process to review and perform translations.") }} +
    +
    + + + {{ $t("Select a screen from the process to review and perform translations.") }} +
    +
    + + +
    +
    @@ -138,6 +145,7 @@ export default { availableLanguages: [], selectedLanguage: null, selectedScreen: null, + currentScreenTitleTranslation: "", screensTranslations: [], currentScreenTranslations: [], stringsWithTranslations: {}, @@ -186,6 +194,8 @@ export default { this.currentScreenTranslations.push(translations.strings[key]); }); } + + this.currentScreenTitleTranslation = val.translations[this.selectedLanguage.language].screen_title; }, selectedLanguage() { From fdd6357fe638feea781f1c944bb9125fbbfead5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Fri, 2 Jun 2023 16:52:55 -0300 Subject: [PATCH 13/47] Revert "Add screen title translations" This reverts commit c886fb8540983c3bb138fae179f55e5bb89a423f. --- .../ScreenTitleLanguageTranslationHandler.php | 86 ------------------ .../language_translation_screen_title.md | 8 -- .../ExecuteScreenTitleTranslationRequest.php | 88 ------------------- .../Jobs/ExecuteTranslationRequest.php | 6 -- .../ProcessTranslations/BatchesJobHandler.php | 19 +--- .../ProcessTranslation.php | 7 -- .../CreateProcessTranslationModal.vue | 30 +++---- 7 files changed, 11 insertions(+), 233 deletions(-) delete mode 100644 ProcessMaker/Ai/Handlers/ScreenTitleLanguageTranslationHandler.php delete mode 100644 ProcessMaker/Ai/Prompts/language_translation_screen_title.md delete mode 100644 ProcessMaker/Jobs/ExecuteScreenTitleTranslationRequest.php diff --git a/ProcessMaker/Ai/Handlers/ScreenTitleLanguageTranslationHandler.php b/ProcessMaker/Ai/Handlers/ScreenTitleLanguageTranslationHandler.php deleted file mode 100644 index c643132676..0000000000 --- a/ProcessMaker/Ai/Handlers/ScreenTitleLanguageTranslationHandler.php +++ /dev/null @@ -1,86 +0,0 @@ -config = [ - 'model' => 'text-davinci-003', - 'max_tokens' => 500, - 'temperature' => 0, - 'top_p' => 1, - 'n' => 1, - 'frequency_penalty' => 0, - 'presence_penalty' => 0, - 'stop' => 'END_', - ]; - } - - public function setTargetLanguage($language) - { - $this->targetLanguage = $language; - } - - public function getPromptFile($type = null) - { - return file_get_contents($this->getPromptsPath() . 'language_translation_' . $type . '.md'); - } - - public function generatePrompt(String $type = null, String $string) : Object - { - $prompt = $this->getPromptFile($type); - $prompt = $this->replaceString($prompt, $string); - $prompt = $this->replaceLanguage($prompt, $this->targetLanguage); - $prompt = $this->replaceStopSequence($prompt); - $this->config['prompt'] = $prompt; - - return $this; - } - - public function execute() - { - $client = app(Client::class); - $response = $client - ->completions() - ->create(array_merge($this->getConfig())); - - return $this->formatResponse($response); - } - - private function formatResponse($response) - { - $result = ltrim($response->choices[0]->text); - $result = rtrim(rtrim(str_replace("\n", '', $result))); - $result = str_replace('\'', '', $result); - - return [$result, $response->usage, $this->question]; - } - - public function replaceStopSequence($prompt) - { - $replaced = str_replace('{stopSequence}', $this->config['stop'] . " \n", $prompt); - - return $replaced; - } - - public function replaceString($prompt, $json_list) - { - $replaced = str_replace('{replaceString}', $json_list . " \n", $prompt); - - return $replaced; - } - - public function replaceLanguage($prompt, $language) - { - $replaced = str_replace('{language}', $language . " \n", $prompt); - - return $replaced; - } -} diff --git a/ProcessMaker/Ai/Prompts/language_translation_screen_title.md b/ProcessMaker/Ai/Prompts/language_translation_screen_title.md deleted file mode 100644 index 5054847922..0000000000 --- a/ProcessMaker/Ai/Prompts/language_translation_screen_title.md +++ /dev/null @@ -1,8 +0,0 @@ -You are an i18n-compatible translation service. You know how to do high quality human translations. Translate the strings within the JSON. Maintain whitespace. Do not modify or translate interpolated variables in any way. You are going to translate the strings in the following json to the language {language}. Respect capital letters. - - -{stopSequence} -Translate the following string: -{replaceString} -{stopSequence} -Response: \ No newline at end of file diff --git a/ProcessMaker/Jobs/ExecuteScreenTitleTranslationRequest.php b/ProcessMaker/Jobs/ExecuteScreenTitleTranslationRequest.php deleted file mode 100644 index 490c05b473..0000000000 --- a/ProcessMaker/Jobs/ExecuteScreenTitleTranslationRequest.php +++ /dev/null @@ -1,88 +0,0 @@ -screen = $screen; - $this->handler = $languageTranslationHandler; - $this->type = $type; - $this->targetLanguage = $targetLanguage; - } - - /** - * Execute the job. - * - * @return void - */ - public function handle() - { - \Log::info('Calling OpenAI for screen title translation...'); - $this->handler->generatePrompt( - $this->type, - $this->screen['title'], - ); - - [$response, $usage, $targetLanguage] = $this->handler->execute(); - - $saved = $this->saveTranslationsInScreen($this->screen['id'], $response); - } - - private function saveTranslationsInScreen($screenId, $screenTitleTranslation) - { - if (!$screenTitleTranslation) { - return; - } - - $screen = Screen::findOrFail($screenId); - $screenTranslations = $screen->translations; - - if (!$screenTranslations || !array_key_exists($this->targetLanguage['language'], $screenTranslations)) { - $screenTranslations[$this->targetLanguage['language']]['screenTitle'] = []; - } - - $screenTranslations[$this->targetLanguage['language']]['screen_title'] = $screenTitleTranslation; - $screenTranslations[$this->targetLanguage['language']]['strings'] = []; - $screenTranslations[$this->targetLanguage['language']]['created_at'] = Carbon::now(); - $screenTranslations[$this->targetLanguage['language']]['updated_at'] = Carbon::now(); - - $screen->translations = $screenTranslations; - $screen->save(); - - \Log::info('Translation title saved OK.'); - } -} diff --git a/ProcessMaker/Jobs/ExecuteTranslationRequest.php b/ProcessMaker/Jobs/ExecuteTranslationRequest.php index e6dbb7ebad..778f6450f6 100644 --- a/ProcessMaker/Jobs/ExecuteTranslationRequest.php +++ b/ProcessMaker/Jobs/ExecuteTranslationRequest.php @@ -80,10 +80,6 @@ private function saveTranslationsInScreen($screenId, $chunkResponse) $screenTranslations[$this->targetLanguage['language']]['strings'] = []; } - if (!array_key_exists('strings', $screenTranslations[$this->targetLanguage['language']])) { - $screenTranslations[$this->targetLanguage['language']]['strings'] = []; - } - $strings = $screenTranslations[$this->targetLanguage['language']]['strings']; // For each of the result chunkResponse translations of the screen foreach ($chunkResponse as $item) { @@ -102,9 +98,7 @@ private function saveTranslationsInScreen($screenId, $chunkResponse) } } - $translatedScreenTitle = $screenTranslations[$this->targetLanguage['language']]['screen_title']; $screenTranslations[$this->targetLanguage['language']]['strings'] = $strings; - $screenTranslations[$this->targetLanguage['language']]['screen_title'] = ($translatedScreenTitle && $translatedScreenTitle !== '' ? $translatedScreenTitle : ''); $screenTranslations[$this->targetLanguage['language']]['created_at'] = Carbon::now(); $screenTranslations[$this->targetLanguage['language']]['updated_at'] = Carbon::now(); diff --git a/ProcessMaker/ProcessTranslations/BatchesJobHandler.php b/ProcessMaker/ProcessTranslations/BatchesJobHandler.php index 743f774947..8c93553fe3 100644 --- a/ProcessMaker/ProcessTranslations/BatchesJobHandler.php +++ b/ProcessMaker/ProcessTranslations/BatchesJobHandler.php @@ -5,8 +5,6 @@ use Illuminate\Bus\Batch; use Illuminate\Support\Facades\Bus; use ProcessMaker\Ai\Handlers\LanguageTranslationHandler; -use ProcessMaker\Ai\Handlers\ScreenTitleLanguageTranslationHandler; -use ProcessMaker\Jobs\ExecuteScreenTitleTranslationRequest; use ProcessMaker\Jobs\ExecuteTranslationRequest; use ProcessMaker\Models\ProcessTranslationToken; use ProcessMaker\Models\User; @@ -49,14 +47,12 @@ public function __construct($process, $screens, $targetLanguage, $code, $user, $ */ public function handle() { - $screenTitleLanguageTranslationHandler = new ScreenTitleLanguageTranslationHandler(); - $screenTitleLanguageTranslationHandler->setTargetLanguage($this->targetLanguage['humanLanguage']); - $languageTranslationHandler = new LanguageTranslationHandler(); $languageTranslationHandler->setTargetLanguage($this->targetLanguage['humanLanguage']); [$screensWithChunks, $chunksCount] = $this->prepareData($this->screens, $languageTranslationHandler); // Execute requests for each regular chunk + $batch = Bus::batch([]) ->then(function (Batch $batch) { \Log::info('All jobs in batch completed'); @@ -83,19 +79,6 @@ public function handle() // Update with real batch token ... ProcessTranslationToken::where('token', $this->code)->update(['token' => $batch->id]); - // Translate screen titles - foreach ($this->screens as $screen) { - $batch->add( - new ExecuteScreenTitleTranslationRequest( - $screen, - $screenTitleLanguageTranslationHandler, - 'screen_title', - $this->targetLanguage - ) - ); - } - - // Translate screen strings chunks foreach ($screensWithChunks as $screenId => $screenWithChunks) { foreach ($screenWithChunks as $chunk) { $batch->add( diff --git a/ProcessMaker/ProcessTranslations/ProcessTranslation.php b/ProcessMaker/ProcessTranslations/ProcessTranslation.php index 6215187561..0ae3210f43 100644 --- a/ProcessMaker/ProcessTranslations/ProcessTranslation.php +++ b/ProcessMaker/ProcessTranslations/ProcessTranslation.php @@ -95,17 +95,11 @@ public function getTranslatedLanguageList($screensTranslations) foreach ($screenTranslation['translations'] as $key => $translation) { $createdAt = $translation['created_at']; $updatedAt = $translation['updated_at']; - $screenTitle = ''; - - if (array_key_exists('screen_title', $translation)) { - $screenTitle = $translation['screen_title']; - } // If updated is greater than existing in array, modify it with the newest if (array_key_exists($key, $languages)) { $createdAt = $languages[$key]['createdAt']; $updatedAt = $languages[$key]['updatedAt']; - $screenTitle = $languages[$key]['screen_title']; if ($languages[$key]['updatedAt'] < $translation['updated_at']) { $createdAt = $translation['created_at']; $updatedAt = $translation['updated_at']; @@ -118,7 +112,6 @@ public function getTranslatedLanguageList($screensTranslations) 'humanLanguage' => Languages::ALL[$key], 'createdAt' => $createdAt, 'updatedAt' => $updatedAt, - 'screen_title' => $screenTitle, ]; } } diff --git a/resources/js/processes/translations/components/CreateProcessTranslationModal.vue b/resources/js/processes/translations/components/CreateProcessTranslationModal.vue index 20f683f27c..9f6fd6db1c 100644 --- a/resources/js/processes/translations/components/CreateProcessTranslationModal.vue +++ b/resources/js/processes/translations/components/CreateProcessTranslationModal.vue @@ -56,24 +56,17 @@
    -
    -
    - - - {{ $t("Select a screen from the process to review and perform translations.") }} -
    -
    - - -
    +
    + + + {{ $t("Select a screen from the process to review and perform translations.") }}
    -
    @@ -145,7 +138,6 @@ export default { availableLanguages: [], selectedLanguage: null, selectedScreen: null, - currentScreenTitleTranslation: "", screensTranslations: [], currentScreenTranslations: [], stringsWithTranslations: {}, @@ -194,8 +186,6 @@ export default { this.currentScreenTranslations.push(translations.strings[key]); }); } - - this.currentScreenTitleTranslation = val.translations[this.selectedLanguage.language].screen_title; }, selectedLanguage() { From dcf8eab751895d3a423c86d3bae44f68e9f96c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Mon, 5 Jun 2023 09:46:49 -0300 Subject: [PATCH 14/47] Redirect after import --- resources/views/processes/translations/import.blade.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/views/processes/translations/import.blade.php b/resources/views/processes/translations/import.blade.php index 5ce91086ca..7be8614614 100644 --- a/resources/views/processes/translations/import.blade.php +++ b/resources/views/processes/translations/import.blade.php @@ -147,6 +147,7 @@ class="p-0" let message = this.$t('The process translation was imported correctly.'); let variant = 'success'; ProcessMaker.alert(message, variant); + window.location.href = `/processes/${this.process.id}/edit`; }) .catch((error) => { this.submitted = false; From bb4545dfe81dc54a9ce6d66605ac20c187735860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Mon, 5 Jun 2023 11:55:49 -0300 Subject: [PATCH 15/47] Fix error in console --- resources/js/components/shared/EllipsisMenu.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/components/shared/EllipsisMenu.vue b/resources/js/components/shared/EllipsisMenu.vue index f36d42cdf8..8218ba1b02 100644 --- a/resources/js/components/shared/EllipsisMenu.vue +++ b/resources/js/components/shared/EllipsisMenu.vue @@ -15,7 +15,7 @@ :class="customButton.icon" /> - {{ customButton.content }} {{ data.batchInfo.progress }}% + {{ customButton.content }} {{ data.batchInfo.progress }}%