-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #62 from AcclaroInc/release/1.7.0
Release/1.7.0
- Loading branch information
Showing
13 changed files
with
933 additions
and
3 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
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
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
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,32 @@ | ||
<?php | ||
/** | ||
* Translations for Craft plugin for Craft CMS 3.x | ||
* | ||
* Translations for Craft eliminates error prone and costly copy/paste workflows for launching human translated Craft CMS web content. | ||
* | ||
* @link http://www.acclaro.com/ | ||
* @copyright Copyright (c) 2018 Acclaro | ||
*/ | ||
|
||
namespace acclaro\translations\assetbundles; | ||
|
||
use craft\web\AssetBundle; | ||
use craft\web\assets\cp\CpAsset; | ||
|
||
class StaticTranslationsAssets extends AssetBundle | ||
{ | ||
public function init() | ||
{ | ||
$this->sourcePath = '@acclaro/translations/assetbundles/src'; | ||
|
||
$this->depends = [ | ||
CpAsset::class, | ||
]; | ||
|
||
$this->js = [ | ||
'js/StaticTranslations.js', | ||
]; | ||
|
||
parent::init(); | ||
} | ||
} |
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 |
---|---|---|
|
@@ -625,3 +625,7 @@ | |
.translations-about .link a { | ||
padding-right: 15px; | ||
} | ||
|
||
.static-trans-footer .pagination { | ||
display: none; | ||
} |
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,93 @@ | ||
(function($) { | ||
|
||
if (typeof Craft.Translations === 'undefined') { | ||
Craft.Translations = {}; | ||
} | ||
|
||
Craft.Translations.StaticTranslations = { | ||
|
||
saveStaticTranslation: function() { | ||
|
||
var data = $("#static-translation").serializeArray(); | ||
data.push( | ||
{name: 'source', value: Craft.elementIndex.sourceKey}, | ||
{name: 'siteId', value: Craft.elementIndex.siteId} | ||
); | ||
Craft.postActionRequest('translations/static-translations/save', data, $.proxy(function(response, textStatus) { | ||
if (textStatus === 'success') { | ||
if (response.success) { | ||
Craft.cp.displayNotice(Craft.t('app', 'Static Translations saved.')); | ||
Craft.elementIndex.updateElements(); | ||
} | ||
} else { | ||
Craft.cp.displayError(Craft.t('app', 'An unknown error occurred.')); | ||
} | ||
|
||
$('.save-static-translation').removeClass('disabled'); | ||
$('.save-static-translation').attr("disabled", false); | ||
|
||
}, this)); | ||
|
||
|
||
}, | ||
|
||
exportStaticTranslation: function() { | ||
|
||
var data = { | ||
siteId: Craft.elementIndex.siteId, | ||
sourceKey: Craft.elementIndex.sourceKey, | ||
search: Craft.elementIndex.searchText | ||
}; | ||
|
||
Craft.postActionRequest('translations/static-translations/export', data, $.proxy(function(response, textStatus) { | ||
if (textStatus === 'success') { | ||
if (response.success) { | ||
var $iframe = $('<iframe/>', {'src': Craft.getActionUrl('translations/static-translations/export-file', {'filename': response.filePath})}).hide(); | ||
$('#static-translation').append($iframe); | ||
Craft.cp.displayNotice(Craft.t('app', 'Static Translations exported.')); | ||
} | ||
} else { | ||
Craft.cp.displayError(Craft.t('app', 'An unknown error occurred.')); | ||
} | ||
}, this)); | ||
|
||
}, | ||
|
||
init: function() { | ||
var self = this; | ||
$('.sortmenubtn').hide(); | ||
$('.statusmenubtn').hide(); | ||
$(".sitemenubtn").appendTo("#toolbar"); | ||
|
||
$('.save-static-translation').on('click', function(e) { | ||
|
||
$('.save-static-translation').addClass('disabled'); | ||
$('.save-static-translation').attr("disabled", true); | ||
|
||
e.preventDefault(); | ||
console.log(Craft.elementIndex); | ||
self.saveStaticTranslation(); | ||
}); | ||
|
||
$('#translate-export').on('click', function(e) { | ||
|
||
e.preventDefault(); | ||
if($(".elements table:first tr").length > 1) { | ||
self.exportStaticTranslation(); | ||
} else { | ||
Craft.cp.displayNotice(Craft.t('app', 'No Translations to export.')); | ||
} | ||
}); | ||
|
||
$('.translate-import').click(function() { | ||
|
||
$('input[name="trans-import"]').click().change(function() { | ||
$('#siteId').val(Craft.elementIndex.siteId); | ||
$(this).parent('form').submit(); | ||
}); | ||
|
||
}); | ||
}, | ||
}; | ||
|
||
})(jQuery); |
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,196 @@ | ||
<?php | ||
/** | ||
* Translations for Craft plugin for Craft CMS 3.x | ||
* | ||
* Translations for Craft eliminates error prone and costly copy/paste workflows for launching human translated Craft CMS web content. | ||
* | ||
* @link http://www.acclaro.com/ | ||
* @copyright Copyright (c) 2018 Acclaro | ||
*/ | ||
|
||
namespace acclaro\translations\controllers; | ||
|
||
use Craft; | ||
use craft\helpers\Path; | ||
use craft\web\Controller; | ||
use yii\web\UploadedFile; | ||
use craft\helpers\StringHelper; | ||
use yii\web\NotFoundHttpException; | ||
use acclaro\translations\Translations; | ||
use acclaro\translations\elements\StaticTranslations; | ||
|
||
/** | ||
* @author Acclaro | ||
* @package Translations | ||
* @since 1.0.0 | ||
*/ | ||
class StaticTranslationsController extends Controller | ||
{ | ||
/** | ||
* @return mixed | ||
*/ | ||
public function actionIndex() { | ||
|
||
$variables = []; | ||
$variables['selectedSubnavItem'] = 'static-translations'; | ||
|
||
$this->requireLogin(); | ||
$this->renderTemplate('translations/static-translations/index', $variables); | ||
} | ||
|
||
/** | ||
* @return \yii\web\Response | ||
* @throws \yii\web\BadRequestHttpException | ||
*/ | ||
public function actionSave() { | ||
|
||
$this->requirePostRequest(); | ||
|
||
$siteId = Craft::$app->request->getRequiredBodyParam('siteId'); | ||
$site = Craft::$app->getSites()->getSiteById($siteId); | ||
$lang = $site->language; | ||
$translations = Craft::$app->request->getRequiredBodyParam('translation'); | ||
|
||
Translations::$plugin->staticTranslationsRepository->set($lang, $translations); | ||
|
||
return $this->asJson([ | ||
'success' => true, | ||
'errors' => [] | ||
]); | ||
} | ||
|
||
/** | ||
* @return \yii\web\Response | ||
* @throws \craft\errors\SiteNotFoundException | ||
* @throws \yii\base\Exception | ||
* @throws \yii\web\BadRequestHttpException | ||
*/ | ||
public function actionExport() { | ||
|
||
$this->requirePostRequest(); | ||
|
||
$siteId = Craft::$app->request->getRequiredBodyParam('siteId'); | ||
$source = Craft::$app->request->getRequiredBodyParam('sourceKey'); | ||
$source = str_replace('*', '/', $source); | ||
|
||
$elementQuery = StaticTranslations::find(); | ||
$elementQuery->status = null; | ||
$elementQuery->source = [$source]; | ||
$elementQuery->search = Craft::$app->request->getRequiredBodyParam('search', null); | ||
$elementQuery->siteId = $siteId; | ||
|
||
$translations = Translations::$plugin->staticTranslationsRepository->get($elementQuery); | ||
|
||
$site = Craft::$app->getSites()->getSiteById($siteId); | ||
$lang = Craft::$app->getI18n()->getLocaleById($site->language); | ||
|
||
$primary = Craft::$app->getSites()->getPrimarySite(); | ||
$primaryLang = Craft::$app->getI18n()->getLocaleById($primary->language); | ||
$langName = ucfirst(StringHelper::convertToUTF8($lang->displayName)); | ||
|
||
$data = '"' .Translations::$plugin->translator->translate('app', "Source: $primaryLang->displayName ($primary->language)") . '","' . Translations::$plugin->translator->translate('app', "Target: $langName ($site->language)") . "\"\r\n"; | ||
foreach ($translations as $row) { | ||
$trans = StringHelper::convertToUTF8($row->translation); | ||
$data .= '"' . $row->original . '","' . $trans . "\"\r\n"; | ||
} | ||
|
||
$file = Craft::$app->getPath()->getTempPath() . DIRECTORY_SEPARATOR . 'StaticTranslations-'.$site->language.'-'.date('Ymdhis') . '.csv'; | ||
$fd = fopen($file, "w"); | ||
fputs($fd, $data); | ||
fclose($fd); | ||
|
||
return $this->asJson([ | ||
'success' => true, | ||
'filePath' => $file | ||
]); | ||
} | ||
|
||
/** | ||
* Export Functionality | ||
* Sends the csv file created to the user | ||
*/ | ||
public function actionExportFile() | ||
{ | ||
$filename = Craft::$app->getRequest()->getRequiredQueryParam('filename'); | ||
if (!is_file($filename) || !Path::ensurePathIsContained($filename)) { | ||
throw new NotFoundHttpException(Craft::t('app', 'Invalid file name: {filename}', [ | ||
'filename' => $filename | ||
])); | ||
} | ||
|
||
return Craft::$app->getResponse()->sendFile($filename, null, ['inline' => true]); | ||
} | ||
|
||
/** | ||
* @throws \yii\web\BadRequestHttpException | ||
*/ | ||
public function actionImport(){ | ||
|
||
$this->requireLogin(); | ||
$this->requirePostRequest(); | ||
|
||
try { | ||
|
||
$siteId = Craft::$app->getRequest()->getRequiredBodyParam('siteId'); | ||
$site = Craft::$app->getSites()->getSiteById($siteId); | ||
|
||
// Upload the file and drop it in the temporary folder | ||
$file = UploadedFile::getInstanceByName('trans-import'); | ||
|
||
// validate file | ||
if (!$this->validateFile($file)) { | ||
Craft::$app->getSession()->setError(Craft::t('app', 'Invalid file type')); | ||
} else { | ||
|
||
$rows = []; | ||
$handle = fopen($file->tempName, 'r'); | ||
|
||
while (($row = fgetcsv($handle)) !== false) { | ||
if (isset($row[0]) && isset($row[1])) { | ||
$rows[$row[0]] = $row[1]; | ||
} | ||
} | ||
fclose($handle); | ||
|
||
if ($rows) { | ||
Translations::$plugin->staticTranslationsRepository->set($site->language, $rows); | ||
Craft::$app->getSession()->setNotice(Craft::t('app', 'Translations imported successfully')); | ||
} else { | ||
Craft::$app->getSession()->setError(Craft::t('app', 'No translation imported')); | ||
} | ||
} | ||
} catch (\Exception $e) { | ||
Craft::$app->getSession()->setError(Craft::t('app', 'Error: '.$e->getMessage())); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* @param $file | ||
* @return bool | ||
*/ | ||
public function validateFile($file) | ||
{ | ||
if ($file->getExtension() !== 'csv') { | ||
return false; | ||
} | ||
|
||
$mimeTypes = [ | ||
'text/csv', | ||
'text/plain', | ||
'application/csv', | ||
'application/txt', | ||
'application/excel', | ||
'application/vnd.msexcel', | ||
'application/vnd.ms-excel', | ||
'text/comma-separated-values', | ||
]; | ||
|
||
if (!in_array($file->type, $mimeTypes)) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
} |
Oops, something went wrong.