-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First version of TranslateAutomator plugin
- Loading branch information
1 parent
e70f760
commit 746b810
Showing
8 changed files
with
263 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?php namespace DavidProvaznik\TranslateAutomator; | ||
|
||
use RainLab\Translate\Classes\Locale; | ||
use System\Classes\PluginBase; | ||
use Event; | ||
use Input; | ||
use Response; | ||
use DavidProvaznik\TranslateAutomator\Models\TranslateAutomator as HelperModel; | ||
|
||
class Plugin extends PluginBase | ||
{ | ||
/** @var string[] $require Required plugins. */ | ||
public $require = [ | ||
'Rainlab.Translate', | ||
]; | ||
public function pluginDetails() | ||
{ | ||
return [ | ||
'name' => 'Translate Automator', | ||
'description' => 'Automate translation of untranslated strings using Google Translate.', | ||
'author' => 'David Provaznik', | ||
'icon' => 'icon-language' | ||
]; | ||
} | ||
|
||
public function boot() | ||
{ | ||
// Extend the view to add custom button | ||
Event::listen('backend.page.beforeDisplay', function($controller, $action, $params) { | ||
if ($controller instanceof \RainLab\Translate\Controllers\Messages && $action == 'index') { | ||
$controller->addJs('/plugins/davidprovaznik/translateautomator/assets/js/translateautomator.js'); | ||
$controller->addCss('/plugins/davidprovaznik/translateautomator/assets/css/translateautomator.css'); | ||
$controller->addDynamicMethod('onTranslate', function() { | ||
$text = Input::get('text'); | ||
$localeTo = Input::get('locale_to'); | ||
$defaultLocale = Locale::getDefaultSiteLocale(); | ||
|
||
$translatedText = HelperModel::autoTranslate($text, $defaultLocale, $localeTo); | ||
|
||
return Response::json(['translatedText' => $translatedText]); | ||
}); | ||
} | ||
}); | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
document.addEventListener('DOMContentLoaded', function () { | ||
console.log('DOM fully loaded and parsed'); | ||
initTranslateButton(); | ||
|
||
// Regularly check for the presence of the button and re-add if necessary | ||
setInterval(function () { | ||
initTranslateButton(); | ||
}, 1000); // Check every second | ||
}); | ||
|
||
let isTranslating = false; | ||
let translateTimeouts = []; | ||
|
||
function initTranslateButton() { | ||
var toolbar = document.querySelector('.loading-indicator-container'); | ||
if (toolbar && !document.querySelector('.btn-translate')) { | ||
addTranslateButton(toolbar); | ||
} else { | ||
// If the button already exists, reattach the click event to handle button state | ||
var button = document.querySelector('.btn-translate'); | ||
if (button) { | ||
button.removeEventListener('click', handleButtonClick); | ||
button.addEventListener('click', handleButtonClick); | ||
} | ||
} | ||
} | ||
|
||
function addTranslateButton(toolbar) { | ||
var button = document.createElement('button'); | ||
button.innerHTML = 'Start Automatic translate if empty'; | ||
button.className = 'btn btn-primary oc-icon-language btn-translate'; | ||
button.addEventListener('click', handleButtonClick); | ||
|
||
toolbar.appendChild(button); | ||
console.log('Translate button added'); | ||
} | ||
|
||
function handleButtonClick() { | ||
console.log('Translate button clicked'); | ||
var button = this; | ||
if (isTranslating) { | ||
stopTranslating(button); | ||
} else { | ||
startTranslating(button); | ||
} | ||
} | ||
|
||
function startTranslating(button) { | ||
isTranslating = true; | ||
button.innerHTML = 'Stop translating...'; | ||
handleTranslateButtonClick(button); | ||
} | ||
|
||
function stopTranslating(button) { | ||
isTranslating = false; | ||
button.innerHTML = 'Translate "from" to "to" if "to" is empty'; | ||
translateTimeouts.forEach(clearTimeout); | ||
translateTimeouts = []; | ||
} | ||
|
||
function handleTranslateButtonClick(button) { | ||
console.log('handleTranslateButtonClick function called'); | ||
var fromCells = document.querySelectorAll('td[data-column="from"]'); | ||
var localeTo = document.querySelector('input[name="locale_to"]').value; | ||
|
||
var delay = 1000; // 1 second delay | ||
|
||
var translatableCells = []; | ||
|
||
// Filter out cells that need translation | ||
fromCells.forEach(function (fromCell) { | ||
var toCell = fromCell.parentNode.querySelector('td[data-column="to"]'); | ||
if (toCell) { | ||
var toValue = toCell.querySelector('input[data-container="data-container"]').value; | ||
if (!toValue) { | ||
translatableCells.push({ fromCell: fromCell, toCell: toCell }); | ||
} | ||
} | ||
}); | ||
|
||
console.log('Translatable cells:', translatableCells); | ||
|
||
// Translate and save each cell | ||
translatableCells.forEach(function (cells, index) { | ||
let timeout = setTimeout(function () { | ||
if (!isTranslating) return; // Stop if translation was stopped | ||
var fromValue = cells.fromCell.querySelector('input[data-container="data-container"]').value; | ||
var key = cells.fromCell.parentNode.getAttribute('data-row'); | ||
|
||
console.log('From value:', fromValue); | ||
console.log('Key:', key); | ||
|
||
if (key) { | ||
$.request('onTranslate', { | ||
data: { | ||
text: fromValue, | ||
locale_to: localeTo | ||
}, | ||
success: function(data) { | ||
console.log('Translation response:', data); | ||
var inputElement = cells.toCell.querySelector('input[data-container="data-container"]'); | ||
var divElement = cells.toCell.querySelector('div[data-view-container="data-view-container"]'); | ||
if (inputElement && divElement) { | ||
inputElement.value = data.translatedText; | ||
divElement.innerText = data.translatedText; | ||
|
||
// Call function to save translated data | ||
saveTranslatedData(fromValue, data.translatedText, localeTo, key); | ||
} | ||
}, | ||
error: function(error) { | ||
console.error('Error translating text:', error); | ||
} | ||
}); | ||
} | ||
}, index * delay); | ||
translateTimeouts.push(timeout); | ||
}); | ||
|
||
// Reset the button state and text when translation completes | ||
if (translatableCells.length > 0) { | ||
let lastTimeout = setTimeout(function () { | ||
stopTranslating(button); | ||
}, translatableCells.length * delay); | ||
translateTimeouts.push(lastTimeout); | ||
} | ||
} | ||
|
||
function saveTranslatedData(fromValue, toValue, localeTo, key) { | ||
var sessionKey = document.querySelector('input[name="_session_key"]').value; | ||
var token = document.querySelector('input[name="_token"]').value; | ||
|
||
var payload = { | ||
_session_key: sessionKey, | ||
_token: token, | ||
search: '', | ||
locale_to: localeTo, | ||
key: key, | ||
'recordData[from]': fromValue, | ||
'recordData[to]': toValue | ||
}; | ||
|
||
$.request('onServerUpdateRecord', { | ||
data: payload, | ||
success: function(response) { | ||
console.log('Translation saved successfully:', response); | ||
}, | ||
error: function(error) { | ||
console.error('Error saving translation:', error); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"name": "davidprovaznik/translateautomator-plugin", | ||
"description": "Automate translation of untranslated strings using Google Translate.", | ||
"type": "october-plugin", | ||
"keywords": ["traslate", "automatic translate"], | ||
"require": { | ||
"php": ">=8.2", | ||
"ext-json": "*", | ||
"composer/installers": "^1.10", | ||
"rainlab/translate-plugin": "^2.1", | ||
"stichoza/google-translate-php": "^5.1" | ||
}, | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "David Provaznik", | ||
"email": "[email protected]" | ||
} | ||
], | ||
"minimum-stability": "stable" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php namespace DavidProvaznik\TranslateAutomator\Models; | ||
|
||
use Model; | ||
use Stichoza\GoogleTranslate\GoogleTranslate; | ||
use Log; | ||
use Exception; | ||
|
||
class TranslateAutomator extends Model | ||
{ | ||
public static function autoTranslate($text, $sourceLocale, $targetLocale) | ||
{ | ||
try { | ||
$tr = new GoogleTranslate(); | ||
$tr->setSource($sourceLocale); | ||
$tr->setTarget($targetLocale); | ||
|
||
$translatedText = $tr->translate($text); | ||
|
||
return $translatedText; | ||
} catch (Exception $e) { | ||
Log::error('Google Translate API error: ' . $e->getMessage()); | ||
throw new Exception("Error communicating with Google Translate API: " . $e->getMessage()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
plugin: | ||
name: 'Translate Automator' | ||
description: 'Automate translation of untranslated strings using Google Translate.' | ||
author: 'David Provaznik' | ||
icon: oc-icon-cogs | ||
homepage: 'https://davidprovaznik.cz' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
1.0.0: | ||
- First version of TranslateAutomator plugin. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<div class="layout"> | ||
<div class="layout-row"> | ||
<div class="layout-cell"> | ||
<button | ||
class="btn btn-primary" | ||
data-request="onTranslate" | ||
data-load-indicator="Translating..."> | ||
Translate Untranslated Strings | ||
</button> | ||
</div> | ||
</div> | ||
</div> |