From 364370ae49441bd014e9f61fb8b2e4f3e8a394bf Mon Sep 17 00:00:00 2001 From: Nate Wright Date: Fri, 20 Mar 2020 11:02:56 +0000 Subject: [PATCH 1/5] Add preliminary code for using Vue.js --- CustomLocalePlugin.inc.php | 7 ++ .../grid/CustomLocaleGridHandler.inc.php | 17 ++-- controllers/grid/form/LocaleFileForm.inc.php | 29 ++---- js/customLocale.js | 54 +++++++++++ templates/localeFile.tpl | 93 +++++++++---------- 5 files changed, 119 insertions(+), 81 deletions(-) create mode 100644 js/customLocale.js diff --git a/CustomLocalePlugin.inc.php b/CustomLocalePlugin.inc.php index fa454ba..9cf022b 100644 --- a/CustomLocalePlugin.inc.php +++ b/CustomLocalePlugin.inc.php @@ -46,6 +46,13 @@ function register($category, $path, $mainContextId = null) { HookRegistry::register('LoadComponentHandler', array($this, 'setupGridHandler')); HookRegistry::register('Template::Settings::website', array($this, 'callbackShowWebsiteSettingsTabs')); HookRegistry::register('LoadHandler', array($this, 'handleLoadRequest')); + + $templateMgr = TemplateManager::getManager($request); + $templateMgr->addJavaScript( + 'customLocale', + $request->getBaseUrl() . '/' . $this->getPluginPath() . '/js/customLocale.js', + ['contexts' => 'backend'] + ); } return true; diff --git a/controllers/grid/CustomLocaleGridHandler.inc.php b/controllers/grid/CustomLocaleGridHandler.inc.php index 7524eb7..a028dd7 100644 --- a/controllers/grid/CustomLocaleGridHandler.inc.php +++ b/controllers/grid/CustomLocaleGridHandler.inc.php @@ -65,27 +65,22 @@ function updateLocale($args, $request) { $searchKey = ''; if (isset($args['searchKey'])) {$searchKey=$args['searchKey'];}; $searchString = $args['searchString']; - // don't save changes if the locale is searched - if (!$searchKey) { - // save changes - $changes = $args['changes']; - + // save changes + $changes = (array) $args['changes']; + if (!empty($changes)) { import('lib.pkp.classes.file.ContextFileManager'); $contextFileManager = new ContextFileManager($context->getId()); $customFilesDir = $contextFileManager->getBasePath() . "customLocale/$locale/"; $customFilePath = "$customFilesDir/$filename"; - if ($args['nextPage']) $currentPage = $args['nextPage']; - if ($contextFileManager->fileExists($customFilePath)) { $translations = Gettext\Translations::fromPoFile($customFilePath); } else { $translations = new \Gettext\Translations(); } - while (!empty($changes)) { - $key = array_shift($changes); - $value = str_replace("\r\n", "\n", array_shift($changes)); + foreach ($changes as $key => $value) { + $value = str_replace("\r\n", "\n", $value); if (!empty($value)) { $translation = $translations->find('', $key); if ($translation) { @@ -101,10 +96,12 @@ function updateLocale($args, $request) { } } } + $contextFileManager->mkdirtree(dirname($customFilePath)); $translations->toPoFile($customFilePath); } + $context = $request->getContext(); $this->setupTemplate($request); diff --git a/controllers/grid/form/LocaleFileForm.inc.php b/controllers/grid/form/LocaleFileForm.inc.php index 90f6fa7..a011dbd 100755 --- a/controllers/grid/form/LocaleFileForm.inc.php +++ b/controllers/grid/form/LocaleFileForm.inc.php @@ -52,29 +52,14 @@ function fetch($request, $currentPage=0, $searchKey='', $searchString='') { if ($contextFileManager->fileExists($customLocalePath)) $localeContents = LocaleFile::load($customLocalePath); else $localeContents = null; $referenceLocaleContents = LocaleFile::load($file); - - $numberOfItemsPerPage = 30; - $numberOfPages = ceil(sizeof($referenceLocaleContents) / $numberOfItemsPerPage); - - if ($searchKey) { - - $keysReferenceLocaleContents = array_keys($referenceLocaleContents); - $keyPosition = array_search($searchString, $keysReferenceLocaleContents); - - if ($keyPosition==0) { - $currentPage = 1; - } - - if ($keyPosition>0) { - $currentPage = floor($keyPosition/$numberOfItemsPerPage)+1; - } - + $referenceLocaleContentsArray = []; + foreach ($referenceLocaleContents as $key => $value) { + $referenceLocaleContentsArray[] = [ + 'localeKey' => $key, + 'value' => $value, + ]; } - // set page number, default: go to first page - if (!$currentPage){ - $currentPage=1; - } $dropdownEntries = array(); for ($i=1; $i<=$numberOfPages; $i++) { @@ -91,10 +76,10 @@ function fetch($request, $currentPage=0, $searchKey='', $searchString='') { 'filePath' => $this->filePath, 'localeContents' => $localeContents, 'locale' => $locale, + 'referenceLocaleContentsArray' => $referenceLocaleContentsArray, 'currentPage' => $currentPage, 'dropdownEntries' => $dropdownEntries, 'searchString' => $searchString, - 'referenceLocaleContents' => new ArrayItemIterator(LocaleFile::load($file), $currentPage, $numberOfItemsPerPage), )); return parent::fetch($request); diff --git a/js/customLocale.js b/js/customLocale.js new file mode 100644 index 0000000..232d26b --- /dev/null +++ b/js/customLocale.js @@ -0,0 +1,54 @@ +var customLocalesApp = {}; +$(function() { + customLocalesApp = { + el: '#customLocales', + data: { + edited: {}, + localeKeys: [], + currentLocaleKeys: [], + searchPhrase: '', + currentPage: 0, + itemsPerPage: 50, + }, + methods: { + search: function() { + if (!this.searchPhrase) { + return; + } + this.currentPage = 1; + var currentLocaleKeys = []; + for (var i in this.localeKeys) { + if (new RegExp(this.searchPhrase, 'i' ).test(this.localeKeys[i].localeKey) + || new RegExp(this.searchPhrase, 'i' ).test(this.localeKeys[i].value)) { + currentLocaleKeys.push({ + localeKey: this.localeKeys[i].localeKey, + value: this.localeKeys[i].value, + }); + } + } + this.currentLocaleKeys = currentLocaleKeys; + } + }, + computed: { + maxPages: function() { + if (!this.localeKeys.length) { + return 0; + } + return Math.ceil(this.localeKeys.length / this.itemsPerPage); + } + }, + watch: { + currentPage: function(newVal, oldVal) { + if (newVal === oldVal) { + return; + } + var end = newVal * this.itemsPerPage; + var start = end - this.itemsPerPage; + this.currentLocaleKeys = this.localeKeys.slice(start, end); + } + }, + mounted: function() { + this.currentPage = 1; + }, + }; +}); \ No newline at end of file diff --git a/templates/localeFile.tpl b/templates/localeFile.tpl index 934fb7e..6abc91d 100644 --- a/templates/localeFile.tpl +++ b/templates/localeFile.tpl @@ -25,58 +25,53 @@ {/literal} +
- -

{translate key="plugins.generic.customLocale.file.edit" filename=$filePath|escape}

- - - - -

{translate key="plugins.generic.customLocale.searchDescription"}



- - - - - - - - - - {iterate from=referenceLocaleContents key=key item=referenceValue} - {assign var=filenameEscaped value=$filename|escape:"url"|escape:"url"} - - -
 
{translate key="plugins.generic.customLocale.localeKey"}{translate key="plugins.generic.customLocale.localeKeyValue"}
 
{$key|escape} - - {if $localeContents != null}{assign var=value value=$localeContents.$key}{else}{assign var=value value=''}{/if} - {if ($value|explode:"\n"|@count > 1) || (strlen($value) > 80) || ($referenceValue|explode:"\n"|@count > 1) || (strlen($referenceValue) > 80)} - {translate key="plugins.generic.customLocale.file.reference"}
- - {translate key="plugins.generic.customLocale.file.custom"}
- - {else} - {translate key="plugins.generic.customLocale.file.reference"}
-
- {translate key="plugins.generic.customLocale.file.custom"}
- - {/if} +
+ +
+ Pages: + +
+ + + + + - {/iterate} -
{{ localeKey.localeKey }}{{ localeKey.value }} +
- - - - {fbvFormButtons id="submitCustomLocaleFileTemplate" submitText="plugins.generic.customLocale.saveAndContinue"} +
+ {fbvFormButtons id="submitCustomLocaleFileTemplate" submitText="plugins.generic.customLocale.saveAndContinue"} +
+ \ No newline at end of file From 32646b1f7d992efbb94824f95ef31de228194398 Mon Sep 17 00:00:00 2001 From: Erik Hanson Date: Wed, 25 Mar 2020 14:01:04 -0700 Subject: [PATCH 2/5] Update frontend/UI to use Vue.js --- .../grid/CustomLocaleGridHandler.inc.php | 10 +- controllers/grid/form/LocaleFileForm.inc.php | 18 +- css/customLocale.css | 44 ++-- js/customLocale.js | 59 +++-- locale/de_DE/locale.po | 6 + locale/en_US/locale.po | 6 + templates/localeFile.tpl | 215 +++++++++++++----- 7 files changed, 248 insertions(+), 110 deletions(-) diff --git a/controllers/grid/CustomLocaleGridHandler.inc.php b/controllers/grid/CustomLocaleGridHandler.inc.php index a028dd7..0017bf9 100644 --- a/controllers/grid/CustomLocaleGridHandler.inc.php +++ b/controllers/grid/CustomLocaleGridHandler.inc.php @@ -61,9 +61,6 @@ function updateLocale($args, $request) { $contextId = $context->getId(); $locale = $args['locale']; $filename = $args['key']; - $currentPage = $args['currentPage']; - $searchKey = ''; if (isset($args['searchKey'])) {$searchKey=$args['searchKey'];}; - $searchString = $args['searchString']; // save changes $changes = (array) $args['changes']; @@ -99,6 +96,11 @@ function updateLocale($args, $request) { $contextFileManager->mkdirtree(dirname($customFilePath)); $translations->toPoFile($customFilePath); + + // Create success notification and close modal on save + $notificationMgr = new NotificationManager(); + $notificationMgr->createTrivialNotification($request->getUser()->getId()); + return new JSONMessage(false); } @@ -111,7 +113,7 @@ function updateLocale($args, $request) { $localeFileForm = new LocaleFileForm(self::$plugin, $filename, $locale); $localeFileForm->initData(); - return new JSONMessage(true, $localeFileForm->fetch($request, $currentPage, $searchKey, $searchString)); + return new JSONMessage(true, $localeFileForm->fetch($request)); } // diff --git a/controllers/grid/form/LocaleFileForm.inc.php b/controllers/grid/form/LocaleFileForm.inc.php index a011dbd..629d243 100755 --- a/controllers/grid/form/LocaleFileForm.inc.php +++ b/controllers/grid/form/LocaleFileForm.inc.php @@ -36,11 +36,8 @@ function __construct($customLocalePlugin, $filePath, $locale) { /** * @copydoc Form::fetch - * @param $currentPage int - * @param $searchKey string - * @param $searchString string */ - function fetch($request, $currentPage=0, $searchKey='', $searchString='') { + function fetch($request) { $file = $this->filePath; $locale = $this->locale; if (!CustomLocaleAction::isLocaleFile($locale, $file)) throw new Exception("$file is not a locale file!"); @@ -60,16 +57,6 @@ function fetch($request, $currentPage=0, $searchKey='', $searchString='') { ]; } - - $dropdownEntries = array(); - for ($i=1; $i<=$numberOfPages; $i++) { - if ($i==$currentPage) { - $dropdownEntries[$i] = "stay on page " . $i; - } else { - $dropdownEntries[$i] = "go to page " . $i; - } - } - import('lib.pkp.classes.core.ArrayItemIterator'); $templateMgr = TemplateManager::getManager($request); $templateMgr->assign(array( @@ -77,9 +64,6 @@ function fetch($request, $currentPage=0, $searchKey='', $searchString='') { 'localeContents' => $localeContents, 'locale' => $locale, 'referenceLocaleContentsArray' => $referenceLocaleContentsArray, - 'currentPage' => $currentPage, - 'dropdownEntries' => $dropdownEntries, - 'searchString' => $searchString, )); return parent::fetch($request); diff --git a/css/customLocale.css b/css/customLocale.css index 9251ea9..070f0e3 100644 --- a/css/customLocale.css +++ b/css/customLocale.css @@ -6,10 +6,6 @@ * */ -.highlight { - background-color: #A9E2F3; -} - td.input { border-top: 1px solid #999; padding: 15px 10px 5px 10px; @@ -19,18 +15,40 @@ input.valueChanged, textArea.valueChanged { background-color:#FFFF93 !important; } -input, textArea { - background-color:#eee !important; +.customLocale__headerDescription { + padding-top: 0.5rem; + font-size: 14px; + line-height: 1.6em; +} + +.pkpTable td.customLocale__itemCount { + font-size: 12px; + padding: 0.5rem 1rem; +} + +.customLocale__cellTable { + border: inherit; +} +.customLocale__cellTable tr { + border-bottom: inherit; +} +/* .customLocale__cellTable { + border-bottom: 1px solid #eee; +} */ + +.customLocale__cellHeader td { + font-weight: bold; +} + +.customLocale__keyHeader { + padding-bottom: 0.5rem; } -#nextPage { - width:150px; +textarea.customLocale__fixedSize { + resize: none; } -#searchString { - float:left; - width: 520px; - margin: 3px 10px 0px 0px; - padding: 0; +.activeTest { + font-weight: bold; } diff --git a/js/customLocale.js b/js/customLocale.js index 232d26b..505ae4e 100644 --- a/js/customLocale.js +++ b/js/customLocale.js @@ -4,37 +4,60 @@ $(function() { el: '#customLocales', data: { edited: {}, - localeKeys: [], - currentLocaleKeys: [], + filePath: '', + localEdited: {}, // temporarily holds edited values, both saved and new + localeKeysMaster: [], // master list of all keys in locale file + filteredKeysList: [], // filtered keys allows for paginating search results + currentLocaleKeys: [], // keys available on a given page searchPhrase: '', currentPage: 0, itemsPerPage: 50, + displaySearchResults: false, }, methods: { search: function() { if (!this.searchPhrase) { + this.initializeView(); return; } - this.currentPage = 1; - var currentLocaleKeys = []; - for (var i in this.localeKeys) { - if (new RegExp(this.searchPhrase, 'i' ).test(this.localeKeys[i].localeKey) - || new RegExp(this.searchPhrase, 'i' ).test(this.localeKeys[i].value)) { - currentLocaleKeys.push({ - localeKey: this.localeKeys[i].localeKey, - value: this.localeKeys[i].value, + + this.displaySearchResults = true; + this.currentPage = -1; + var filteredKeysList = []; + for (var i in this.localeKeysMaster) { + if (new RegExp(this.searchPhrase, 'i' ).test(this.localeKeysMaster[i].localeKey) + || new RegExp(this.searchPhrase, 'i' ).test(this.localeKeysMaster[i].value)) { + filteredKeysList.push({ + localeKey: this.localeKeysMaster[i].localeKey, + value: this.localeKeysMaster[i].value, }); } } - this.currentLocaleKeys = currentLocaleKeys; + + // Similar to initializeView, but uses search results rather than master list + this.currentPage = 1; + var end = this.currentPage * this.itemsPerPage; + var start = end - this.itemsPerPage; + this.filteredKeysList = filteredKeysList; + this.currentLocaleKeys = this.filteredKeysList.slice(start,end); + }, + initializeView: function() { + this.searchPhrase = ""; + this.currentPage = 1; + this.displaySearchResults = false; + + this.filteredKeysList = this.localeKeysMaster; // Filtering changes + var end = this.currentPage * this.itemsPerPage; + var start = end - this.itemsPerPage; + this.currentLocaleKeys = this.filteredKeysList.slice(start,end); } }, computed: { maxPages: function() { - if (!this.localeKeys.length) { + if (!this.filteredKeysList.length) { return 0; } - return Math.ceil(this.localeKeys.length / this.itemsPerPage); + return Math.ceil(this.filteredKeysList.length / this.itemsPerPage); } }, watch: { @@ -44,11 +67,17 @@ $(function() { } var end = newVal * this.itemsPerPage; var start = end - this.itemsPerPage; - this.currentLocaleKeys = this.localeKeys.slice(start, end); + this.currentLocaleKeys = this.filteredKeysList.slice(start, end); // Filtering changes + } }, mounted: function() { - this.currentPage = 1; + this.initializeView(); + // merges edited into localEdited + this.localEdited = {} // TODO: Should all changes be cleared when searching? + for (var attrName in this.edited) { + this.localEdited[attrName] = this.edited[attrName]; + } }, }; }); \ No newline at end of file diff --git a/locale/de_DE/locale.po b/locale/de_DE/locale.po index d67f445..66c64bb 100644 --- a/locale/de_DE/locale.po +++ b/locale/de_DE/locale.po @@ -50,6 +50,9 @@ msgstr "Anpassen" msgid "grid.action.printChanges" msgstr "Hier können Sie eine Datei downloaden, die alle Anpassungen auflistet." +msgid "plugins.generic.customLocale.file.editHeader" +msgstr "Regionaleinstellung anpassen" + msgid "plugins.generic.customLocale.file.edit" msgstr "{$filename} bearbeiten" @@ -70,3 +73,6 @@ msgstr "Regionaleinstellungsdateien" msgid "plugins.generic.customLocale.fileDescription" msgstr "Geben Sie den angepassten Text in das jeweilige Feld ein. Lassen Sie das Feld leer, wenn der OMP-Standardtext genutzt werden soll." + +msgid "plugins.generic.customLocale.searchResultsCount" +msgstr "{{ currentLocaleKeys.length }} von {{ filteredKeysList.length }} Ergebnissen ausgegeben." \ No newline at end of file diff --git a/locale/en_US/locale.po b/locale/en_US/locale.po index abfef82..5228219 100644 --- a/locale/en_US/locale.po +++ b/locale/en_US/locale.po @@ -50,6 +50,9 @@ msgstr "Customize" msgid "grid.action.printChanges" msgstr "Download a file that lists all the customizations you made." +msgid "plugins.generic.customLocale.file.editHeader" +msgstr "Customize locale keys" + msgid "plugins.generic.customLocale.file.edit" msgstr "Editing {$filename}" @@ -73,3 +76,6 @@ msgstr "Enter a complete locale key here. Keys found are highlighted." msgid "plugins.generic.customLocale.fileDescription" msgstr "Enter text into corresponding custom text field. Leave custom text field blank if the default OMP text should be used." + +msgid "plugins.generic.customLocale.searchResultsCount" +msgstr "Displaying {{ currentLocaleKeys.length }} of {{ filteredKeysList.length }} results." \ No newline at end of file diff --git a/templates/localeFile.tpl b/templates/localeFile.tpl index 6abc91d..93572cd 100644 --- a/templates/localeFile.tpl +++ b/templates/localeFile.tpl @@ -6,72 +6,165 @@ * *} - - - - - - - -
+ +
- -
- Pages: - -
- + {* TABLE *} +
+ {* TABLE HEADER *} + + + + + {* MAIN BODY *} - -
+ +

{translate key="plugins.generic.customLocale.file.editHeader"}

+
+
+ {* SEARCH BOX *} + +
+
+ {translate key="plugins.generic.customLocale.file.edit" filename=$filePath|escape} +
+
+ {translate key="plugins.generic.customLocale.searchResultsCount"} +
{{ localeKey.localeKey }}{{ localeKey.value }} - + + + + + + + + +
{{ localeKey.localeKey }}
+
{translate key="plugins.generic.customLocale.file.reference"}
+
+ +
+
+ +
+
+
{translate key="plugins.generic.customLocale.file.custom"}
+
+ +
+
+ +
+
+ + {* PAGINATION *} + + + + {fbvFormButtons id="submitCustomLocaleFileTemplate" submitText="plugins.generic.customLocale.saveAndContinue"}
-
- \ No newline at end of file + + \ No newline at end of file From 66f576488a6d14d3cae2a866143163904ab8c6bc Mon Sep 17 00:00:00 2001 From: Erik Hanson Date: Wed, 29 Apr 2020 17:16:59 -0700 Subject: [PATCH 3/5] Accessibility changes to UI --- css/customLocale.css | 7 ------- js/customLocale.js | 16 ++++++++++------ locale/de_DE/locale.po | 2 +- locale/en_US/locale.po | 2 +- templates/localeFile.tpl | 20 ++++++++++++-------- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/css/customLocale.css b/css/customLocale.css index 070f0e3..c1e5568 100644 --- a/css/customLocale.css +++ b/css/customLocale.css @@ -32,18 +32,11 @@ input.valueChanged, textArea.valueChanged { .customLocale__cellTable tr { border-bottom: inherit; } -/* .customLocale__cellTable { - border-bottom: 1px solid #eee; -} */ .customLocale__cellHeader td { font-weight: bold; } -.customLocale__keyHeader { - padding-bottom: 0.5rem; -} - textarea.customLocale__fixedSize { resize: none; } diff --git a/js/customLocale.js b/js/customLocale.js index 505ae4e..fe48587 100644 --- a/js/customLocale.js +++ b/js/customLocale.js @@ -10,6 +10,7 @@ $(function() { filteredKeysList: [], // filtered keys allows for paginating search results currentLocaleKeys: [], // keys available on a given page searchPhrase: '', + phraseSearched: '', currentPage: 0, itemsPerPage: 50, displaySearchResults: false, @@ -20,14 +21,16 @@ $(function() { this.initializeView(); return; } - + this.phraseSearched = this.searchPhrase; this.displaySearchResults = true; this.currentPage = -1; var filteredKeysList = []; for (var i in this.localeKeysMaster) { - if (new RegExp(this.searchPhrase, 'i' ).test(this.localeKeysMaster[i].localeKey) - || new RegExp(this.searchPhrase, 'i' ).test(this.localeKeysMaster[i].value)) { - filteredKeysList.push({ + if ( + new RegExp(this.searchPhrase, 'i' ).test(this.localeKeysMaster[i].localeKey) + || new RegExp(this.searchPhrase, 'i' ).test(this.localeKeysMaster[i].value) + ) { + filteredKeysList.push({ localeKey: this.localeKeysMaster[i].localeKey, value: this.localeKeysMaster[i].value, }); @@ -42,7 +45,8 @@ $(function() { this.currentLocaleKeys = this.filteredKeysList.slice(start,end); }, initializeView: function() { - this.searchPhrase = ""; + this.searchPhrase = ''; + this.phraseSearched = ''; this.currentPage = 1; this.displaySearchResults = false; @@ -74,7 +78,7 @@ $(function() { mounted: function() { this.initializeView(); // merges edited into localEdited - this.localEdited = {} // TODO: Should all changes be cleared when searching? + this.localEdited = {} for (var attrName in this.edited) { this.localEdited[attrName] = this.edited[attrName]; } diff --git a/locale/de_DE/locale.po b/locale/de_DE/locale.po index 66c64bb..1965120 100644 --- a/locale/de_DE/locale.po +++ b/locale/de_DE/locale.po @@ -75,4 +75,4 @@ msgid "plugins.generic.customLocale.fileDescription" msgstr "Geben Sie den angepassten Text in das jeweilige Feld ein. Lassen Sie das Feld leer, wenn der OMP-Standardtext genutzt werden soll." msgid "plugins.generic.customLocale.searchResultsCount" -msgstr "{{ currentLocaleKeys.length }} von {{ filteredKeysList.length }} Ergebnissen ausgegeben." \ No newline at end of file +msgstr "{{ currentLocaleKeys.length }} von {{ filteredKeysList.length }} Ergebnissen für \"{{ phraseSearched }}\" ausgegeben." \ No newline at end of file diff --git a/locale/en_US/locale.po b/locale/en_US/locale.po index 5228219..464fd09 100644 --- a/locale/en_US/locale.po +++ b/locale/en_US/locale.po @@ -78,4 +78,4 @@ msgid "plugins.generic.customLocale.fileDescription" msgstr "Enter text into corresponding custom text field. Leave custom text field blank if the default OMP text should be used." msgid "plugins.generic.customLocale.searchResultsCount" -msgstr "Displaying {{ currentLocaleKeys.length }} of {{ filteredKeysList.length }} results." \ No newline at end of file +msgstr "Displaying {{ currentLocaleKeys.length }} of {{ filteredKeysList.length }} results for \"{{ phraseSearched }}.\"" \ No newline at end of file diff --git a/templates/localeFile.tpl b/templates/localeFile.tpl index 93572cd..6a164b4 100644 --- a/templates/localeFile.tpl +++ b/templates/localeFile.tpl @@ -18,13 +18,13 @@
{* SEARCH BOX *} -
{translate key="plugins.generic.customLocale.file.edit" filename=$filePath|escape} @@ -54,7 +56,7 @@ {* MAIN BODY *} - + @@ -62,10 +64,11 @@
-
{translate key="plugins.generic.customLocale.file.reference"}
+
-