diff --git a/.gitignore b/.gitignore index a547c0bff..90c0df18f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ nginx-ssl.error.log php-errors.log sftp-config.json selenium.php + +# for netbeans +nbproject diff --git a/CHANGELOG.md b/CHANGELOG.md index 666233583..28204ea51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +* **Build 292** (2015-08-28) + - Added a new controller method `fireViewEvent()` for extending views and partials (see Plugins > Events docs). + - Fixes a bug where the database falls asleep during an update. + +* **Build 290** (2015-08-15) + - Added test base class for developers who want to test their plugins with phpunit. See the readme file in the **tests/** directory for more details. + * **Build 289** (2015-08-07) - Added new `makeFormWidget()` method to `WidgetMaker` trait for rendering form widgets individually. This method is now available to backend controllers, controller behaviors and widgets themselves. Check to make sure your classes do not define a conflicting method of this name. diff --git a/README.md b/README.md index 668cd2bf9..dfd714366 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ You can communicate with us using the following mediums: * [Follow us on Twitter](http://twitter.com/octobercms) for announcements and updates. * [Follow us on Facebook](http://facebook.com/octobercms) for announcements and updates. -* [Join us on IRC](https://kiwiirc.com/client/irc.freenode.net/?nick=Octonaut|?#october) to chat with us. +* [Join us on IRC](http://octobercms.com/chat) to chat with us. ### License diff --git a/composer.json b/composer.json index 689a1a371..1f4983e48 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,8 @@ "autoload-dev": { "classmap": [ "tests/TestCase.php", - "tests/UiTestCase.php" + "tests/UiTestCase.php", + "tests/PluginTestCase.php" ] }, "scripts": { diff --git a/modules/backend/assets/css/october.css b/modules/backend/assets/css/october.css index 9929ecce8..cf7af82a3 100644 --- a/modules/backend/assets/css/october.css +++ b/modules/backend/assets/css/october.css @@ -116,6 +116,10 @@ .sweet-alert .btn-danger:focus{border-color:#d43f3a;outline:0} .sweet-alert .btn-warning:focus{border-color:#eea236;outline:0} .sweet-alert button::-moz-focus-inner{border:0} +.sweet-alert{text-align:right} +.sweet-alert h4{word-break:word-break;word-wrap:break-word;max-height:350px;overflow-y:auto;margin:10px 0 17px 0;color:#2b3e50;text-align:left;font-size:15px;line-height:23px} +.sweet-alert p{margin:0} +.sweet-alert p.text-muted{margin-bottom:20px;color:#555555} .control-simplelist{font-size:13px} .control-simplelist ul{padding-left:15px} .control-simplelist.form-control ul{margin-bottom:0} @@ -228,9 +232,6 @@ .tooltip.in{opacity:1;filter:alpha(opacity=100)} .oc-logo-white{background-image:url(../images/october-logo-white.svg);background-position:50% 50%;background-repeat:no-repeat;background-size:contain} .oc-bg-logo{background-image:url(../images/october-logo-transparent.svg);background-position:50% 50%;background-repeat:no-repeat;background-size:50% auto} -.sweet-alert{text-align:left} -.sweet-alert h4{margin:10px 0 20px 0;color:#2b3e50;font-size:18px} -.sweet-alert p.text-muted{margin-bottom:20px;color:#555555} .report-widget{padding:15px;background:white;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px} .report-widget h3{font-size:14px;color:#7e8c8d;text-transform:uppercase;font-weight:600;margin-top:0;margin-bottom:30px} .report-widget .height-100{height:100px} @@ -582,7 +583,6 @@ body{webkit-font-smoothing:antialiased;font-family:'Open Sans',Arial,sans-serif; .layout > .layout-row > .layout-cell.min-height{height:0} .layout > .layout-row > .layout-cell.center{text-align:center} .layout > .layout-row > .layout-cell.middle{vertical-align:middle} -.layout > .layout-row > .layout-cell.width-fix > form,.layout > .layout-row > .layout-cell.width-fix > div{display:inline-block} .layout > .layout-row > .layout-cell.width-100{width:100px} .layout > .layout-row > .layout-cell.width-120{width:120px} .layout > .layout-row > .layout-cell.width-200{width:200px} @@ -595,7 +595,6 @@ body{webkit-font-smoothing:antialiased;font-family:'Open Sans',Arial,sans-serif; .layout > .layout-row > .layout-cell.min-height{height:0} .layout > .layout-row > .layout-cell.center{text-align:center} .layout > .layout-row > .layout-cell.middle{vertical-align:middle} -.layout > .layout-row > .layout-cell.width-fix > form,.layout > .layout-row > .layout-cell.width-fix > div{display:inline-block} .layout > .layout-row.min-size{height:0} .layout > .layout-cell{display:table-cell;vertical-align:top;height:100%} .layout > .layout-cell.width-100{width:100px} @@ -610,8 +609,8 @@ body{webkit-font-smoothing:antialiased;font-family:'Open Sans',Arial,sans-serif; .layout > .layout-cell.min-height{height:0} .layout > .layout-cell.center{text-align:center} .layout > .layout-cell.middle{vertical-align:middle} -.layout > .layout-cell.width-fix > form,.layout > .layout-cell.width-fix > div{display:inline-block} .whiteboard{background:white} +.layout-cell.width-fix > form,[data-calculate-width] > form,.layout-cell.width-fix > div,[data-calculate-width] > div{display:inline-block} body.compact-container .layout.layout-container,body.compact-container .layout .layout-container{padding:0 !important} body.slim-container .layout.layout-container,body.slim-container .layout .layout-container{padding-left:0 !important;padding-right:0 !important} @media (max-width:768px){.layout .hide-on-small{display:none} @@ -638,7 +637,7 @@ nav#layout-mainmenu.navbar ul li.account a{padding-right:20px;position:relative; nav#layout-mainmenu.navbar ul li.account img{width:25px;margin-right:7px;position:relative;top:-2px} nav#layout-mainmenu.navbar ul.nav{display:inline-block} nav#layout-mainmenu.navbar .menu-toggle{display:none} -nav#layout-mainmenu.navbar .toolbar-item{margin-right:0} +nav#layout-mainmenu.navbar .toolbar-item{padding-right:0} nav#layout-mainmenu.navbar .toolbar-item:before,nav#layout-mainmenu.navbar .toolbar-item:after{margin-top:0} nav#layout-mainmenu.navbar .toolbar-item:before{left:-12px} nav#layout-mainmenu.navbar .toolbar-item:after{right:-12px} diff --git a/modules/backend/assets/js/backend.js b/modules/backend/assets/js/backend.js index ce18301f8..d8e8839d4 100644 --- a/modules/backend/assets/js/backend.js +++ b/modules/backend/assets/js/backend.js @@ -15,43 +15,6 @@ $.ajaxPrefilter(function(options) { } }) -/* - * Implement "Sweet Alert" with AJAX framework - */ - -$(window).on('ajaxErrorMessage', function(event, message){ - if (!message) return - - swal({ - title: message, - // type: 'error', - confirmButtonClass: 'btn-default' - }) - - // Prevent the default alert() message - event.preventDefault() -}) - -$(window).on('ajaxConfirmMessage', function(event, message){ - if (!message) return - - swal({ - title: message, - // type: 'warning', - showCancelButton: true, - confirmButtonClass: 'btn-primary' - }, - function(isConfirm){ - isConfirm - ? event.promise.resolve() - : event.promise.reject() - }) - - // Prevent the default confirm() message - event.preventDefault() - return true -}) - /* * Path helpers */ diff --git a/modules/backend/assets/js/october-min.js b/modules/backend/assets/js/october-min.js index 28ca8f9eb..5b1bf868d 100644 --- a/modules/backend/assets/js/october-min.js +++ b/modules/backend/assets/js/october-min.js @@ -432,7 +432,8 @@ var $targetElement=e.target||e.srcElement;var btnIndex=-1;for(var i=0;i<$modalBu if(keyCode===9){if(btnIndex===-1){$targetElement=$okButton;}else{if(btnIndex===$modalButtons.length-1){$targetElement=$modalButtons[0];}else{$targetElement=$modalButtons[btnIndex+1];}} stopEventPropagation(e);$targetElement.focus();}else{if(keyCode===13||keyCode===32){if(btnIndex===-1){$targetElement=$okButton;}else{$targetElement=undefined;}}else if(keyCode===27&&!($cancelButton.hidden||$cancelButton.style.display==='none')){$targetElement=$cancelButton;}else{$targetElement=undefined;} if($targetElement!==undefined){fireClick($targetElement,e);}}} -previousWindowKeyDown=window.onkeydown;window.onkeydown=handleKeyDown;function handleOnBlur(e){var $targetElement=e.target||e.srcElement,$focusElement=e.relatedTarget,modalIsVisible=hasClass(modal,'visible');if(modalIsVisible){var btnIndex=-1;if($focusElement!==null){for(var i=0;i<$modalButtons.length;i++){if($focusElement===$modalButtons[i]){btnIndex=i;break;}} +previousWindowKeyDown=window.onkeydown;window.onkeydown=handleKeyDown;function handleOnBlur(e){var $targetElement=e.target||e.srcElement,$focusElement=e.relatedTarget,modalIsVisible=hasClass(modal,'visible'),bootstrapModalIsVisible=document.querySelector('.control-popup.modal')||false;if(bootstrapModalIsVisible){return;} +if(modalIsVisible){var btnIndex=-1;if($focusElement!==null){for(var i=0;i<$modalButtons.length;i++){if($focusElement===$modalButtons[i]){btnIndex=i;break;}} if(btnIndex===-1){$targetElement.focus();}}else{lastFocusedButton=$targetElement;}}} $okButton.onblur=handleOnBlur;$cancelButton.onblur=handleOnBlur;window.onfocus=function(){window.setTimeout(function(){if(lastFocusedButton!==undefined){lastFocusedButton.focus();lastFocusedButton=undefined;}},0);};};window.swal.setDefaults=function(userParams){if(!userParams){throw new Error('userParams is required');} if(typeof userParams!=='object'){throw new Error('userParams has to be a object');} @@ -713,9 +714,25 @@ $.each(name.split('.'),function(index,value){if(result[value]===undefined){resul return false} result=result[value]}) return result} -if(lang.locale===undefined){lang.locale='en'} +if(lang.locale===undefined){lang.locale=$('html').attr('lang')||'en'} if(lang.loadedMessages===undefined){lang.load(lang.locale)} -return lang})($.oc.lang||{},$.oc.langMessages);+function($){"use strict";var Base=$.oc.foundation.base,BaseProto=Base.prototype +return lang})($.oc.lang||{},$.oc.langMessages);(function($){if($.oc===undefined) +$.oc={} +$.oc.alert=function alert(message){swal({title:message,confirmButtonClass:'btn-primary'})} +$.oc.confirm=function confirm(message,callback){swal({title:message,showCancelButton:true,confirmButtonClass:'btn-primary'},callback)}})(jQuery);$(window).on('ajaxErrorMessage',function(event,message){if(!message)return +$.oc.alert(message) +event.preventDefault()}) +$(window).on('ajaxConfirmMessage',function(event,message){if(!message)return +$.oc.confirm(message,function(isConfirm){isConfirm?event.promise.resolve():event.promise.reject()}) +event.preventDefault() +return true}) +$(document).on('ready',function(){if(!window.swal)return +var swal=window.swal +window.sweetAlert=window.swal=function(message,callback){if(typeof message==='object'){message.confirmButtonText=message.confirmButtonText||$.oc.lang.get('alert.confirm_button_text') +message.cancelButtonText=message.cancelButtonText||$.oc.lang.get('alert.cancel_button_text')} +else{message={title:message,confirmButtonText:$.oc.lang.get('alert.confirm_button_text'),cancelButtonText:$.oc.lang.get('alert.cancel_button_text')}} +swal(message,callback)}}) ++function($){"use strict";var Base=$.oc.foundation.base,BaseProto=Base.prototype var Scrollpad=function(element,options){this.$el=$(element) this.scrollbarElement=null this.dragHandleElement=null @@ -867,7 +884,7 @@ return this}}(window.jQuery);(function($){$(window).load(function(){$('nav.navba navbar=$(this),nav=$('ul.nav',navbar) nav.verticalMenu($('a.menu-toggle',navbar)) $('li.with-tooltip > a',navbar).tooltip({container:'body',placement:'bottom'}) -$('.layout-cell.width-fix',navbar).one('oc.widthFixed',function(){var dragScroll=$('[data-control=toolbar]',navbar).data('oc.dragScroll') +$('[data-calculate-width]',navbar).one('oc.widthFixed',function(){var dragScroll=$('[data-control=toolbar]',navbar).data('oc.dragScroll') if(dragScroll){dragScroll.goToElement($('ul.nav > li.active',navbar),undefined,{'duration':0})}})})})})(jQuery);+function($){"use strict";if($.oc===undefined) $.oc={} var SideNav=function(element,options){this.options=options @@ -1073,7 +1090,7 @@ if(this.pageTitleTemplate===undefined) this.pageTitleTemplate=$title.data('titleTemplate') $title.text(this.pageTitleTemplate.replace('%s',title))} OctoberLayout.prototype.updateLayout=function(title){var $children,$el,fixedWidth,margin -$('.layout-cell.width-fix').each(function(){$children=$(this).children() +$('.layout-cell.width-fix, [data-calculate-width]').each(function(){$children=$(this).children() if($children.length>0){fixedWidth=0 $children.each(function(){$el=$(this) margin=$el.data('oc.layoutMargin') @@ -1399,13 +1416,6 @@ return this} $(document).ready(function(){$('[data-control=sidenav-tree]').sidenavTree()})}(window.jQuery);$.ajaxPrefilter(function(options){var token=$('meta[name="csrf-token"]').attr('content') if(token){if(!options.headers)options.headers={} options.headers['X-CSRF-TOKEN']=token}}) -$(window).on('ajaxErrorMessage',function(event,message){if(!message)return -swal({title:message,confirmButtonClass:'btn-default'}) -event.preventDefault()}) -$(window).on('ajaxConfirmMessage',function(event,message){if(!message)return -swal({title:message,showCancelButton:true,confirmButtonClass:'btn-primary'},function(isConfirm){isConfirm?event.promise.resolve():event.promise.reject()}) -event.preventDefault() -return true}) if($.oc===undefined) $.oc={} $.oc.backendUrl=function(url){var backendBasePath=$('meta[name="backend-base-path"]').attr('content') diff --git a/modules/backend/assets/js/october.alert.js b/modules/backend/assets/js/october.alert.js new file mode 100644 index 000000000..08118dc86 --- /dev/null +++ b/modules/backend/assets/js/october.alert.js @@ -0,0 +1,89 @@ +/* + * Alerts + * + * Displays alert and confirmation dialogs + * + * JavaScript API: + * $.oc.alert() + * $.oc.confirm() + * + * Dependences: + * - Sweet Alert + */ +(function($){ + + if ($.oc === undefined) + $.oc = {} + + $.oc.alert = function alert(message) { + swal({ + title: message, + confirmButtonClass: 'btn-primary' + }) + } + + $.oc.confirm = function confirm(message, callback) { + + swal({ + title: message, + showCancelButton: true, + confirmButtonClass: 'btn-primary' + }, callback) + + } + +})(jQuery); + +/* + * Implement alerts with AJAX framework + */ + +$(window).on('ajaxErrorMessage', function(event, message){ + if (!message) return + + $.oc.alert(message) + + // Prevent the default alert() message + event.preventDefault() +}) + +$(window).on('ajaxConfirmMessage', function(event, message){ + if (!message) return + + $.oc.confirm(message, function(isConfirm){ + isConfirm + ? event.promise.resolve() + : event.promise.reject() + }) + + // Prevent the default confirm() message + event.preventDefault() + return true +}) + +/* + * Override "Sweet Alert" functions to translate default buttons + */ + +$(document).on('ready', function(){ + if (!window.swal) return + + var swal = window.swal + + window.sweetAlert = window.swal = function(message, callback) { + if (typeof message === 'object') { + // Do not override if texts are provided + message.confirmButtonText = message.confirmButtonText || $.oc.lang.get('alert.confirm_button_text') + message.cancelButtonText = message.cancelButtonText || $.oc.lang.get('alert.cancel_button_text') + } + else { + message = { + title: message, + confirmButtonText: $.oc.lang.get('alert.confirm_button_text'), + cancelButtonText: $.oc.lang.get('alert.cancel_button_text') + } + } + + swal(message, callback) + } +}) diff --git a/modules/backend/assets/js/october.js b/modules/backend/assets/js/october.js index 61cf0d177..46c563174 100644 --- a/modules/backend/assets/js/october.js +++ b/modules/backend/assets/js/october.js @@ -18,6 +18,7 @@ =require ../../../system/assets/vendor/prettify/prettify.js =require october.lang.js +=require october.alert.js =require october.scrollpad.js =require october.verticalmenu.js =require october.navbar.js diff --git a/modules/backend/assets/js/october.lang.js b/modules/backend/assets/js/october.lang.js index 7777c6731..92ed770e9 100644 --- a/modules/backend/assets/js/october.lang.js +++ b/modules/backend/assets/js/october.lang.js @@ -38,7 +38,7 @@ $.oc.lang = (function(lang, messages) { } if (lang.locale === undefined) { - lang.locale = 'en' + lang.locale = $('html').attr('lang') || 'en' } if (lang.loadedMessages === undefined) { diff --git a/modules/backend/assets/js/october.layout.js b/modules/backend/assets/js/october.layout.js index 2c93cd896..2c2718193 100644 --- a/modules/backend/assets/js/october.layout.js +++ b/modules/backend/assets/js/october.layout.js @@ -15,7 +15,9 @@ OctoberLayout.prototype.updateLayout = function(title) { var $children, $el, fixedWidth, margin - $('.layout-cell.width-fix').each(function(){ + // The entire 'width-fix' class can probably be removed if year >= 2017 + // After checking that it isn't being used anywhere -sg + $('.layout-cell.width-fix, [data-calculate-width]').each(function(){ $children = $(this).children() if ($children.length > 0) { diff --git a/modules/backend/assets/js/october.navbar.js b/modules/backend/assets/js/october.navbar.js index e6e5fc768..df87b29c0 100644 --- a/modules/backend/assets/js/october.navbar.js +++ b/modules/backend/assets/js/october.navbar.js @@ -12,7 +12,7 @@ (function($){ $(window).load(function() { $('nav.navbar').each(function(){ - var + var navbar = $(this), nav = $('ul.nav', navbar) @@ -23,7 +23,7 @@ placement: 'bottom' }) - $('.layout-cell.width-fix', navbar).one('oc.widthFixed', function(){ + $('[data-calculate-width]', navbar).one('oc.widthFixed', function() { var dragScroll = $('[data-control=toolbar]', navbar).data('oc.dragScroll') if (dragScroll) { dragScroll.goToElement($('ul.nav > li.active', navbar), undefined, {'duration': 0}) diff --git a/modules/backend/assets/js/october.simplelist.js b/modules/backend/assets/js/october.simplelist.js index 0add060c2..b26b2a377 100644 --- a/modules/backend/assets/js/october.simplelist.js +++ b/modules/backend/assets/js/october.simplelist.js @@ -1,5 +1,5 @@ /* - * SimpleList control. + * SimpleList control. * * Data attributes: * - data-control="simplelist" - enables the simplelist plugin diff --git a/modules/backend/assets/less/controls/alert.less b/modules/backend/assets/less/controls/alert.less new file mode 100644 index 000000000..66ff9c66d --- /dev/null +++ b/modules/backend/assets/less/controls/alert.less @@ -0,0 +1,30 @@ +// +// Custom alerts (Based on Sweet Alert) +// -------------------------------------------------- + + +.sweet-alert { + text-align: right; + + h4 { + word-break: word-break; + word-wrap: break-word; + max-height: 350px; + overflow-y: auto; + + margin: 10px 0 17px 0; + color: #2b3e50; + text-align: left; + font-size: 15px; + line-height: 23px; + } + + p { + margin: 0; + } + + p.text-muted { + margin-bottom: 20px; + color: #555555; + } +} diff --git a/modules/backend/assets/less/controls/common.less b/modules/backend/assets/less/controls/common.less index c750a0b98..24cc76537 100644 --- a/modules/backend/assets/less/controls/common.less +++ b/modules/backend/assets/less/controls/common.less @@ -43,23 +43,3 @@ background-repeat: no-repeat; background-size: 50% auto; } - - -// -// Alerts -// - -.sweet-alert { - text-align: left; - - h4 { - margin: 10px 0 20px 0; - color: #2b3e50; - font-size: 18px; - } - - p.text-muted { - margin-bottom: 20px; - color: #555555; - } -} \ No newline at end of file diff --git a/modules/backend/assets/less/layout/layout.less b/modules/backend/assets/less/layout/layout.less index 23bdcf019..ad4b4a431 100644 --- a/modules/backend/assets/less/layout/layout.less +++ b/modules/backend/assets/less/layout/layout.less @@ -112,12 +112,6 @@ body { &.middle { vertical-align: middle; } - - &.width-fix { - > form, > div { - display: inline-block; - } - } } display: table; @@ -148,6 +142,16 @@ body { background: white; } +// +// Calculated fixed width +// + +.layout-cell.width-fix, [data-calculate-width] { + > form, > div { + display: inline-block; + } +} + // // Layout styles // diff --git a/modules/backend/assets/less/layout/mainmenu.less b/modules/backend/assets/less/layout/mainmenu.less index 8115f51f2..a687cd28d 100644 --- a/modules/backend/assets/less/layout/mainmenu.less +++ b/modules/backend/assets/less/layout/mainmenu.less @@ -7,8 +7,6 @@ body.mainmenu-open { } nav#layout-mainmenu.navbar { - // .clearfix(); - // position: relative; background-color: @color-mainmenu; height: auto; padding: 0 0 0 20px; @@ -84,7 +82,7 @@ nav#layout-mainmenu.navbar { .menu-toggle { display: none; } .toolbar-item { - margin-right: 0; + padding-right: 0; &:before, &:after { margin-top: 0; } &:before { left: -12px; } diff --git a/modules/backend/assets/less/october.less b/modules/backend/assets/less/october.less index babc2b26d..cb5339d3e 100644 --- a/modules/backend/assets/less/october.less +++ b/modules/backend/assets/less/october.less @@ -21,6 +21,7 @@ // @import "core/boot.less"; +@import "controls/alert.less"; @import "controls/simplelist.less"; @import "controls/scrollbar.less"; @import "controls/filelist.less"; diff --git a/modules/backend/assets/vendor/sweet-alert/sweet-alert.js b/modules/backend/assets/vendor/sweet-alert/sweet-alert.js index 9ca8e0f97..7fff82223 100644 --- a/modules/backend/assets/vendor/sweet-alert/sweet-alert.js +++ b/modules/backend/assets/vendor/sweet-alert/sweet-alert.js @@ -386,7 +386,14 @@ function handleOnBlur(e) { var $targetElement = e.target || e.srcElement, $focusElement = e.relatedTarget, - modalIsVisible = hasClass(modal, 'visible'); + modalIsVisible = hasClass(modal, 'visible'), + bootstrapModalIsVisible = document.querySelector('.control-popup.modal') || false; + + if (bootstrapModalIsVisible) { + // Bootstrap will enforce focus on the existing model, so don't + // do anything here to prevent infinite loop. + return; + } if (modalIsVisible) { var btnIndex = -1; // Find the button - note, this is a nodelist, not an array. diff --git a/modules/backend/behaviors/ReorderController.php b/modules/backend/behaviors/ReorderController.php new file mode 100644 index 000000000..6102b5500 --- /dev/null +++ b/modules/backend/behaviors/ReorderController.php @@ -0,0 +1,266 @@ +config = $this->makeConfig($controller->reorderConfig, $this->requiredConfig); + + /* + * Widgets + */ + if ($this->toolbarWidget = $this->makeToolbarWidget()) { + $this->toolbarWidget->bindToController(); + } + + /* + * Populate from config + */ + $this->nameFrom = $this->getConfig('nameFrom', $this->nameFrom); + } + + // + // Controller actions + // + + public function reorder() + { + $this->addJs('js/october.reorder.js', 'core'); + + $this->controller->pageTitle = $this->controller->pageTitle + ?: Lang::get($this->getConfig('title', 'backend::lang.reorder.default_title')); + + $this->validateModel(); + $this->prepareVars(); + } + + // + // AJAX + // + + public function onReorder() + { + $model = $this->validateModel(); + + /* + * Simple + */ + if ($this->sortMode == 'simple') { + if (!$ids = post('record_ids')) return; + if (!$orders = post('sort_orders')) return; + + $model->setSortableOrder($ids, $orders); + } + /* + * Nested set + */ + elseif ($this->sortMode == 'nested') { + $sourceNode = $model->find(post('sourceNode')); + $targetNode = post('targetNode') ? $model->find(post('targetNode')) : null; + + if ($sourceNode == $targetNode) return; + + switch (post('position')) { + case 'before': + $sourceNode->moveBefore($targetNode); + break; + + case 'after': + $sourceNode->moveAfter($targetNode); + break; + + case 'child': + $sourceNode->makeChildOf($targetNode); + break; + + default: + $sourceNode->makeRoot(); + break; + } + } + } + + // + // Reordering + // + + /** + * Prepares common form data + */ + protected function prepareVars() + { + $this->vars['reorderRecords'] = $this->getRecords(); + $this->vars['reorderModel'] = $this->model; + $this->vars['reorderSortMode'] = $this->sortMode; + $this->vars['reorderShowTree'] = $this->showTree; + $this->vars['reorderToolbarWidget'] = $this->toolbarWidget; + } + + public function reorderRender() + { + return $this->reorderMakePartial('container'); + } + + public function reorderGetModel() + { + if ($this->model !== null) { + return $this->model; + } + + $modelClass = $this->getConfig('modelClass'); + if (!$modelClass) { + throw new ApplicationException('Please specify the modelClass property for reordering'); + } + + return $this->model = new $modelClass; + } + + /** + * Returns the display name for a record. + * @return string + */ + public function reorderGetRecordName($record) + { + return $record->{$this->nameFrom}; + } + + /** + * Validate the supplied form model. + * @return void + */ + protected function validateModel() + { + $model = $this->controller->reorderGetModel(); + $modelTraits = class_uses($model); + + if (isset($modelTraits['October\Rain\Database\Traits\Sortable'])) { + $this->sortMode = 'simple'; + } + elseif (isset($modelTraits['October\Rain\Database\Traits\NestedTree'])) { + $this->sortMode = 'nested'; + $this->showTree = true; + } + else { + throw new ApplicationException('The model must implement the NestedTree or Sortable traits.'); + } + + return $model; + } + + /** + * Returns all the records from the supplied model. + * @return Collection + */ + protected function getRecords() + { + $model = $this->controller->reorderGetModel(); + $records = null; + + if ($this->sortMode == 'simple') { + $records = $model + ->orderBy($model->getSortOrderColumn()) + ->get() + ; + } + elseif ($this->sortMode == 'nested') { + $records = $model->getEagerRoot(); + } + + return $records; + } + + // + // Widgets + // + + protected function makeToolbarWidget() + { + if ($toolbarConfig = $this->getConfig('toolbar')) { + $toolbarConfig = $this->makeConfig($toolbarConfig); + $toolbarWidget = $this->makeWidget('Backend\Widgets\Toolbar', $toolbarConfig); + } + else { + $toolbarWidget = null; + } + + return $toolbarWidget; + } + + // + // Helpers + // + + /** + * Controller accessor for making partials within this behavior. + * @param string $partial + * @param array $params + * @return string Partial contents + */ + public function reorderMakePartial($partial, $params = []) + { + $contents = $this->controller->makePartial('reorder_'.$partial, $params + $this->vars, false); + if (!$contents) { + $contents = $this->makePartial($partial, $params); + } + + return $contents; + } + +} \ No newline at end of file diff --git a/modules/backend/behaviors/reordercontroller/assets/js/october.reorder.js b/modules/backend/behaviors/reordercontroller/assets/js/october.reorder.js new file mode 100644 index 000000000..5ce495748 --- /dev/null +++ b/modules/backend/behaviors/reordercontroller/assets/js/october.reorder.js @@ -0,0 +1,82 @@ +/* + * Scripts for the Reorder controller behavior. + * + * The following functions are observed: + * - Simple sorting: Post back the original sort orders and the new ordered identifiers. + * - Nested sorting: Post back source and target nodes IDs and the move positioning. + */ ++function ($) { "use strict"; + + var ReorderBehavior = function() { + + this.sortMode = null + + this.simpleSortOrders = [] + + this.initSorting = function (mode) { + this.sortMode = mode + + if (mode == 'simple') { + this.initSortingSimple() + } + + $('#reorderTreeList').on('move.oc.treelist', $.proxy(this.processReorder, this)) + } + + + this.processReorder = function(ev, sortData){ + var postData + + if (this.sortMode == 'simple') { + postData = { sort_orders: this.simpleSortOrders } + } + else if (this.sortMode == 'nested') { + postData = this.getNestedMoveData(sortData) + } + + $('#reorderTreeList').request('onReorder', { + data: postData + }) + } + + this.getNestedMoveData = function (sortData) { + var + $el, + $item = sortData.item, + moveData = { + targetNode: 0, + sourceNode: $item.data('recordId'), + position: 'root' + } + + if (($el = $item.next()) && $el.length) { + moveData.position = 'before' + } + else if (($el = $item.prev()) && $el.length) { + moveData.position = 'after' + } + else if (($el = $item.parents('li:first')) && $el.length) { + moveData.position = 'child' + } + + if ($el.length) { + moveData.targetNode = $el.data('recordId') + } + + return moveData + } + + this.initSortingSimple = function () { + var sortOrders = [] + + $('#reorderTreeList li').each(function(){ + sortOrders.push($(this).data('recordSortOrder')) + }) + + this.simpleSortOrders = sortOrders + } + + } + + $.oc.reorderBehavior = new ReorderBehavior; +}(window.jQuery); \ No newline at end of file diff --git a/modules/backend/behaviors/reordercontroller/partials/_container.htm b/modules/backend/behaviors/reordercontroller/partials/_container.htm new file mode 100644 index 000000000..6d329f38a --- /dev/null +++ b/modules/backend/behaviors/reordercontroller/partials/_container.htm @@ -0,0 +1,29 @@ + + +
+ render() ?> +
+ + + + +
+ data-handle=" li > .record > a.move' ?>" + data-stripe-load-indicator> + +
    + reorderMakePartial('records', ['records' => $reorderRecords]) ?> +
+ +

+ +
+ + + diff --git a/modules/backend/behaviors/reordercontroller/partials/_records.htm b/modules/backend/behaviors/reordercontroller/partials/_records.htm new file mode 100644 index 000000000..c85ac1814 --- /dev/null +++ b/modules/backend/behaviors/reordercontroller/partials/_records.htm @@ -0,0 +1,19 @@ + + +
  • +
    + + reorderGetRecordName($record) ?> + +
    + + +
      + children): ?> + reorderMakePartial('records', ['records' => $record->children]) ?> + +
    + +
  • + + \ No newline at end of file diff --git a/modules/backend/classes/NavigationManager.php b/modules/backend/classes/NavigationManager.php index 3ff7ee8ec..764b1f83d 100644 --- a/modules/backend/classes/NavigationManager.php +++ b/modules/backend/classes/NavigationManager.php @@ -273,6 +273,11 @@ class NavigationManager return false; } + $definition = array_merge($definition, [ + 'code' => $sideCode, + 'owner' => $owner + ]); + $mainItem = $this->items[$itemKey]; if (isset($mainItem->sideMenu[$sideCode])) { $definition = array_merge((array) $mainItem->sideMenu[$sideCode], $definition); diff --git a/modules/backend/controllers/auth/signin.htm b/modules/backend/controllers/auth/signin.htm index f5ddccf52..4271bcdf0 100644 --- a/modules/backend/controllers/auth/signin.htm +++ b/modules/backend/controllers/auth/signin.htm @@ -26,6 +26,7 @@ autocomplete="off" maxlength="255" /> + @@ -38,6 +39,7 @@

    - - \ No newline at end of file + + +fireViewEvent('backend.auth.extendSigninView') ?> diff --git a/modules/backend/formwidgets/FileUpload.php b/modules/backend/formwidgets/FileUpload.php index c488b9093..f6470830a 100644 --- a/modules/backend/formwidgets/FileUpload.php +++ b/modules/backend/formwidgets/FileUpload.php @@ -34,9 +34,9 @@ class FileUpload extends FormWidgetBase // /** - * @var string Prompt to display if no record is selected. + * @var string Prompt text to display for the upload button. */ - public $prompt = 'backend::lang.fileupload.default_prompt'; + public $prompt = null; /** * @var int Preview image width @@ -126,7 +126,7 @@ class FileUpload extends FormWidgetBase $this->vars['cssDimensions'] = $this->getCssDimensions(); $this->vars['cssBlockDimensions'] = $this->getCssDimensions('block'); $this->vars['useCaption'] = $this->useCaption; - $this->vars['prompt'] = str_replace('%s', '', trans($this->prompt)); + $this->vars['prompt'] = $this->getPromptText(); } protected function getFileList() @@ -166,6 +166,22 @@ class FileUpload extends FormWidgetBase return $mode; } + /** + * Returns the escaped and translated prompt text to display according to the type. + * @return string + */ + protected function getPromptText() + { + if ($this->prompt === null) { + $isMulti = ends_with($this->getDisplayMode(), 'multi'); + $this->prompt = $isMulti + ? 'backend::lang.fileupload.upload_file' + : 'backend::lang.fileupload.default_prompt'; + } + + return str_replace('%s', '', e(trans($this->prompt))); + } + /** * Returns the CSS dimensions for the uploaded image, * uses auto where no dimension is provided. diff --git a/modules/backend/formwidgets/Repeater.php b/modules/backend/formwidgets/Repeater.php index 7520dbd55..0287756de 100644 --- a/modules/backend/formwidgets/Repeater.php +++ b/modules/backend/formwidgets/Repeater.php @@ -38,10 +38,21 @@ class Repeater extends FormWidgetBase */ protected $defaultAlias = 'repeater'; + /** + * @var int Count of repeated items. + */ protected $indexCount = 0; + /** + * @var array Collection of form widgets. + */ protected $formWidgets = []; + /** + * @var bool Stops nested repeaters populating from previous sibling. + */ + protected static $onAddItemCalled = false; + /** * {@inheritDoc} */ @@ -53,7 +64,9 @@ class Repeater extends FormWidgetBase 'sortable', ]); - $this->processExistingItems(); + if (!self::$onAddItemCalled) { + $this->processExistingItems(); + } } /** @@ -128,6 +141,8 @@ class Repeater extends FormWidgetBase public function onAddItem() { + self::$onAddItemCalled = true; + $this->indexCount++; $this->prepareVars(); diff --git a/modules/backend/formwidgets/fileupload/partials/_file_multi.htm b/modules/backend/formwidgets/fileupload/partials/_file_multi.htm index f4baf3050..6ae8c2d6b 100644 --- a/modules/backend/formwidgets/fileupload/partials/_file_multi.htm +++ b/modules/backend/formwidgets/fileupload/partials/_file_multi.htm @@ -11,8 +11,8 @@ > - diff --git a/modules/backend/formwidgets/markdowneditor/assets/js/markdowneditor.js b/modules/backend/formwidgets/markdowneditor/assets/js/markdowneditor.js index b1c657039..c4433e366 100644 --- a/modules/backend/formwidgets/markdowneditor/assets/js/markdowneditor.js +++ b/modules/backend/formwidgets/markdowneditor/assets/js/markdowneditor.js @@ -169,8 +169,8 @@ MarkdownEditor.prototype.createToolbar = function() { var self = this, $button, - $buttons = $('
    '), - $fixedButtons = $('
    ') + $buttons = $('
    '), + $fixedButtons = $('
    ') $.each($.oc.markdownEditorButtons, function(code, button) { $button = self.makeToolbarButton(code, button) diff --git a/modules/backend/formwidgets/markdowneditor/partials/_markdowneditor.htm b/modules/backend/formwidgets/markdowneditor/partials/_markdowneditor.htm index 160198222..685284f35 100644 --- a/modules/backend/formwidgets/markdowneditor/partials/_markdowneditor.htm +++ b/modules/backend/formwidgets/markdowneditor/partials/_markdowneditor.htm @@ -1,4 +1,3 @@ - previewMode): ?>
    @@ -10,8 +9,7 @@ data-view-mode="" data-vendor-path=""> -
    - +
    diff --git a/modules/backend/formwidgets/recordfinder/partials/_recordfinder_form.htm b/modules/backend/formwidgets/recordfinder/partials/_recordfinder_form.htm index 2b11c962c..df6286554 100644 --- a/modules/backend/formwidgets/recordfinder/partials/_recordfinder_form.htm +++ b/modules/backend/formwidgets/recordfinder/partials/_recordfinder_form.htm @@ -19,4 +19,11 @@
    -
    \ No newline at end of file +
    + + diff --git a/modules/backend/lang/el/lang.php b/modules/backend/lang/el/lang.php index 097a8890b..b98c8deff 100644 --- a/modules/backend/lang/el/lang.php +++ b/modules/backend/lang/el/lang.php @@ -1,5 +1,5 @@ [ 'title' => 'Περιοχή Διαχείρισης', @@ -21,7 +21,7 @@ return [ ], 'invalid_token' => [ 'label' => 'Μη έγκυρο διακριτικό ασφαλείας', - ] + ] ], 'partial' => [ 'not_found_name' => "Το μερικό ':name' δεν βρέθηκε.", @@ -108,7 +108,7 @@ return [ 'code_comment' => 'Συμπληρώστε ένα μοναδικό κωδικό αν θέλετε να έχετε πρόσβαση σε αυτόν μέσω του API.', 'menu_label' => 'Ομάδες', 'list_title' => 'Διαχείριση Ομάδων', - 'new' => 'Νέα Ομάδα Διαχειριστών', + 'new' => 'Νέα Ομάδα', 'delete_confirm' => 'Είστε σίγουροι ότι θέλετε να διαγράψετε αυτήν την ομάδα;', 'return' => 'Επιστροφή στην λίστα των ομάδων', 'users_count' => 'Χρήστες', @@ -145,12 +145,12 @@ return [ 'help' => 'Προσθέστε τίτλο και περιγραφή για αυτήν την επισύναψη.', 'title_label' => 'Τίτλος', 'description_label' => 'Περιγραφή', - 'default_prompt' => 'Κάντε κλικ στο %s ή σύρετε ένα αρχείο εδώ για να το ανεβάσετε',//Click the %s or drag a file here to upload', + 'default_prompt' => 'Κάντε κλικ στο %s ή σύρετε ένα αρχείο εδώ για να το ανεβάσετε', 'attachment_url' => 'URL Συνημμένου', 'upload_file' => 'Ανέβασμα αρχείου', 'upload_error' => 'Σφάλμα ανεβάσματος', 'remove_confirm' => 'Είστε σίγουροι;', - 'remove_file' => 'Διαγραφή αρχείου', + 'remove_file' => 'Διαγραφή αρχείου', ], 'form' => [ 'create_title' => 'Νέο :name', @@ -187,11 +187,12 @@ return [ 'close' => 'Κλείσιμο', 'confirm' => 'Επιβεβαίωση', 'reload' => 'Επαναφόρτιση', + 'complete' => 'Ολοκλήρωση', 'ok' => 'Εντάξει', 'or' => 'ή', 'confirm_tab_close' => 'Είστε σίγουροι ότι θέλετε να κλείσετε αυτήν την καρτέλα; Οι μη αποθηκευμένες αλλαγές θα χαθούν.', 'behavior_not_ready' => 'Η συμπεριφορά δεν έχει αρχικοποιήσεις, ελέγξτε εάν έχετε καλέσει το initForm() στον χειριστή.', - 'preview_no_files_message' => 'Τα αρχεία δεν ανέβηκαν', + 'preview_no_files_message' => 'Δεν υπάρχουν αρχεία που ανέβηκαν.', 'preview_no_record_message' => 'Δεν είναι επιλεγμένη καμία εγγραφή.', 'select' => 'Επιλογή', 'select_all' => 'όλα', diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php index f8d80ef8e..65810c9b6 100644 --- a/modules/backend/lang/en/lang.php +++ b/modules/backend/lang/en/lang.php @@ -237,6 +237,10 @@ return [ 'unlink_name' => 'Unlink :name', 'unlink_confirm' => 'Are you sure?' ], + 'reorder' => [ + 'default_title' => 'Reorder records', + 'no_records' => 'There are no records available to sort.', + ], 'model' => [ 'name' => 'Model', 'not_found' => "Model ':class' with an ID of :id could not be found", @@ -261,6 +265,7 @@ return [ 'code_folding' => 'Code folding', 'word_wrap' => 'Word wrap', 'highlight_active_line' => 'Highlight active line', + 'auto_closing' => 'Auto close tags and special characters', 'show_invisibles' => 'Show invisible characters', 'show_gutter' => 'Show gutter', 'theme' => 'Color scheme' diff --git a/modules/backend/lang/fr/lang.php b/modules/backend/lang/fr/lang.php index c1e1302c3..3511404d4 100644 --- a/modules/backend/lang/fr/lang.php +++ b/modules/backend/lang/fr/lang.php @@ -19,6 +19,9 @@ return [ 'help' => 'Vous n’avez pas l’autorisation de consulter cette page.', 'cms_link' => 'Retour à l’administration' ], + 'invalid_token' => [ + 'label' => 'La clé de sécurité est invalide' + ] ], 'partial' => [ 'not_found_name' => 'Le nom partiel ":name" est introuvable.' @@ -95,6 +98,7 @@ return [ 'allow' => 'Autoriser', 'inherit' => 'Hériter', 'deny' => 'Interdire', + 'account' => 'Compte', 'group' => [ 'name' => 'Groupe', 'name_field' => 'Nom', @@ -140,7 +144,13 @@ return [ 'attachment' => 'Pièce jointe', 'help' => 'Ajouter un titre et une description pour cette pièce jointe.', 'title_label' => 'Titre', - 'description_label' => 'Description' + 'description_label' => 'Description', + 'default_prompt' => 'Cliquer sur %s ou déposer un fichier ici pour le télécharger', + 'attachment_url' => 'Adresse URL du fichier joint', + 'upload_file' => 'Télécharger le fichier', + 'upload_error' => 'Erreur durant le téléchargement', + 'remove_confirm' => 'Confirmer l’action ?', + 'remove_file' => 'Supprimer le fichier', ], 'form' => [ 'create_title' => 'Nouveau :name', @@ -169,19 +179,21 @@ return [ 'resetting' => 'Restauration', 'resetting_name' => 'Restauration de :name', 'undefined_tab' => 'Divers', - 'field_off' => 'Désactivé', - 'field_on' => 'Activé', + 'field_off' => 'Off', + 'field_on' => 'On', 'add' => 'Ajouter', 'apply' => 'Appliquer', 'cancel' => 'Annuler', 'close' => 'Fermer', 'confirm' => 'Confirmer', 'reload' => 'Recharger', + 'complete' => 'Complet', 'ok' => 'OK', 'or' => 'ou', 'confirm_tab_close' => 'Confirmer la fermeture de cet onglet ? Les modifications réalisées seront perdues.', 'behavior_not_ready' => 'Le formulaire n’a pas encore été initialisé, vérifier que la méthode d’appel de initForm() a été soumise au contrôleur.', 'preview_no_files_message' => 'Les fichiers ne sont pas envoyés.', + 'preview_no_record_message' => 'Il n’y a aucun enregistrement sélectionné.', 'select' => 'Sélectionner', 'select_all' => 'tout', 'select_none' => 'aucun', @@ -242,12 +254,13 @@ return [ 'editor' => [ 'menu_label' => 'Préférences de l’éditeur de code', 'menu_description' => 'Personnaliser la configuration de l’éditeur de code, telle que la taille de la police ou la coloration syntaxique.', - 'font_size' => 'Taille de police', - 'tab_size' => 'Taille de tabulation', + 'font_size' => 'Taille de la police', + 'tab_size' => 'Taille de la tabulation', 'use_hard_tabs' => 'Indentation par tabulation', 'code_folding' => 'Masquage du code', 'word_wrap' => 'Retour à la ligne', 'highlight_active_line' => 'Sélectionner la ligne active', + 'auto_closing' => 'Fermer Automatiquement les tags et les caractères spéciaux', 'show_invisibles' => 'Afficher les caractères invisibles', 'show_gutter' => 'Afficher les numéros de ligne', 'theme' => 'Coloration syntaxique' diff --git a/modules/backend/lang/hu/lang.php b/modules/backend/lang/hu/lang.php index 10012e96e..eca44fb3d 100644 --- a/modules/backend/lang/hu/lang.php +++ b/modules/backend/lang/hu/lang.php @@ -28,7 +28,7 @@ return [ ], 'account' => [ 'sign_out' => 'Kijelentkezés', - 'login' => 'Belép', + 'login' => 'Belépés', 'reset' => 'Alaphelyzet', 'restore' => 'Visszaállítás', 'login_placeholder' => 'felhasználónév', @@ -45,7 +45,7 @@ return [ 'reset_error' => 'A megadott jelszó átállítási adatok érvénytelenek. Próbálja újra!', 'reset_fail' => 'Nem állítható vissza a jelszava!', 'apply' => 'Alkalmaz', - 'cancel' => 'Mégse', + 'cancel' => 'Mégsem', 'delete' => 'Törlés', 'ok' => 'OK' ], @@ -79,19 +79,19 @@ return [ 'list_title' => 'Adminisztrátorok kezelése', 'new' => 'Új adminisztrátor', 'login' => 'Felhasználónév', - 'first_name' => 'Keresztnév', - 'last_name' => 'Vezetéknév', + 'first_name' => 'Vezetéknév', + 'last_name' => 'Keresztnév', 'full_name' => 'Teljes név', 'email' => 'E-mail cím', 'groups' => 'Csoportok', - 'groups_comment' => 'Adja meg, hogy ez a felhasználó melyik csoportokba tartozik.', + 'groups_comment' => 'Adja meg, hogy a felhasználó melyik csoportokba tartozik.', 'avatar' => 'Profilkép', 'password' => 'Jelszó', 'password_confirmation' => 'Jelszó megerősítése', 'permissions' => 'Engedélyek', 'account' => 'Fiók', 'superuser' => 'Szuperadmin', - 'superuser_comment' => 'Korlátlan hozzáférés a teljes admin felülethez.', + 'superuser_comment' => 'Korlátlan hozzáférést biztosít a teljes admin felülethez.', 'send_invite' => 'Meghívó küldése e-mailben', 'send_invite_comment' => 'A fentebb megadott adatokat tartalmazza.', 'delete_confirm' => 'Valóban törölni akarja ezt az adminisztrátort?', @@ -183,10 +183,11 @@ return [ 'field_on' => 'Be', 'add' => 'Hozzáadás', 'apply' => 'Alkalmaz', - 'cancel' => 'Mégse', + 'cancel' => 'Mégsem', 'close' => 'Bezárás', 'confirm' => 'Megerősítés', 'reload' => 'Újratöltés', + 'complete' => 'Teljes', 'ok' => 'OK', 'or' => 'vagy', 'confirm_tab_close' => 'Valóban be akarja zárni a fület? El fognak veszni a nem mentett módosítások.', @@ -215,7 +216,7 @@ return [ 'add_a_new' => 'Új :name hozzáadása', 'link_selected' => 'Kijelöltek csatolása', 'link_a_new' => 'Új :name csatolása', - 'cancel' => 'Mégse', + 'cancel' => 'Mégsem', 'close' => 'Bezárás', 'add_name' => ':name hozzáadása', 'create' => 'Létrehozás', @@ -235,6 +236,10 @@ return [ 'unlink_name' => ':name csatolásának megszüntetése', 'unlink_confirm' => 'Biztos benne?' ], + 'reorder' => [ + 'default_title' => 'Elemek újrarendezése', + 'no_records' => 'Nincs elérhető tartalom a rendezéshez.' + ], 'model' => [ 'name' => 'Modell', 'not_found' => "Nem található :id azonosítójú ':class' modell.", @@ -259,6 +264,7 @@ return [ 'code_folding' => 'Kód összecsukása', 'word_wrap' => 'Tördelés', 'highlight_active_line' => 'Aktív sor kiemelése', + 'auto_closing' => 'Automatikus kódlezárás', 'show_invisibles' => 'Láthatatlan karakterek megjelenítése', 'show_gutter' => 'Margó megjelenítése', 'theme' => 'Színséma' @@ -279,8 +285,8 @@ return [ 'menu_label' => 'Admin felület', 'menu_description' => 'A kinézetének módosítása és egyedivé tétele.', 'brand' => 'Márka', - 'logo' => 'Embléma', - 'logo_description' => 'Töltsön fel egy emblémát az admin oldalon való használathoz.', + 'logo' => 'Logó', + 'logo_description' => 'A kép a bejelentkezési felületen, illetve egyes oldalak háttereként fog megjelenni.', 'app_name' => 'Weboldal neve', 'app_name_description' => 'Ez a név látható a bejelentkező képernyőn.', 'app_tagline' => 'Weboldal szlogenje', @@ -303,7 +309,7 @@ return [ 'hint' => 'Ez a napló a felhasználók sikeres bejelentkezési kísérleteit listázza ki. A bejegyzéseket :days napig őrzi meg a rendszer.', 'menu_label' => 'Hozzáférésnapló', 'menu_description' => 'A felhasználók sikeres bejelentkezéseinek megtekintése.', - 'created_at' => 'Dátum és idő', + 'created_at' => 'Időpont', 'login' => 'Felhasználónév', 'ip_address' => 'IP cím', 'first_name' => 'Keresztnév', diff --git a/modules/backend/lang/it/lang.php b/modules/backend/lang/it/lang.php index caa35a56f..62eb0733a 100644 --- a/modules/backend/lang/it/lang.php +++ b/modules/backend/lang/it/lang.php @@ -1,24 +1,30 @@ [ + 'title' => 'Area di Amministrazione' + ], 'field' => [ 'invalid_type' => 'Il tipo di campo :type non è valido.', - 'options_method_not_exists' => 'La classe :model deve definire un metodo :method() che ritorni le opzioni per il campo ":field".', + 'options_method_not_exists' => 'La classe :model deve definire un metodo :method() che ritorni le opzioni per il campo ":field".' ], 'widget' => [ 'not_registered' => "Nessun widget ':name' è stato registrato", 'not_bound' => "Nessun widget ':name' è stato legato al controller", ], 'page' => [ - 'untitled' => "Senza titolo", + 'untitled' => 'Senza titolo', 'access_denied' => [ - 'label' => "Accesso negato", + 'label' => 'Accesso negato', 'help' => "Non hai le autorizzazioni necessarie per accedere a questa pagina.", - 'cms_link' => "Ritorna al pannello di controllo", + 'cms_link' => 'Ritorna al pannello di controllo' ], + 'invalid_token' => [ + 'label' => 'Token di protezione non valido' + ] ], 'partial' => [ - 'not_found_name' => "La vista parziale ':name' non è stata trovata.", + 'not_found_name' => "La vista parziale ':name' non è stata trovata." ], 'account' => [ 'sign_out' => 'Esci', @@ -27,26 +33,27 @@ return [ 'restore' => 'Ripristina', 'login_placeholder' => 'login', 'password_placeholder' => 'password', - 'forgot_password' => "Dimenticato la password?", - 'enter_email' => "Inserisci in tuo indirizzo e-mail", - 'enter_login' => "Inserisci il login.", - 'email_placeholder' => "email", - 'enter_new_password' => "Inserisci una nuova password", - 'password_reset' => "Reimposta password", - 'restore_success' => "Le istruzioni per reimpostare la password sono state inviate al tuo indirizzo e-mail.", - 'restore_error' => "Nessun utente con login ':login' è stato trovato.", - 'reset_success' => "La tua password è stata reimpostata con successo. Ora puoi effettuare l'accesso.", - 'reset_error' => "I dati forniti per la reimpostazione della password non sono validi. Riprova!", - 'reset_fail' => "Impossibile ripristinare la password!", + 'forgot_password' => 'Password dimenticata?', + 'enter_email' => 'Inserisci in tuo indirizzo e-mail', + 'enter_login' => 'Inserisci il tuo username.', + 'email_placeholder' => 'email', + 'enter_new_password' => 'Inserisci una nuova password', + 'password_reset' => 'Reimposta password', + 'restore_success' => 'Le istruzioni per reimpostare la password sono state inviate al tuo indirizzo e-mail.', + 'restore_error' => "Nessun utente con username ':login' è stato trovato.", + 'reset_success' => 'La tua password è stata reimpostata con successo. Ora puoi effettuare l\'accesso.', + 'reset_error' => 'I dati forniti per la reimpostazione della password non sono validi. Riprova!', + 'reset_fail' => 'Impossibile ripristinare la password!', 'apply' => 'Applica', 'cancel' => 'Annulla', 'delete' => 'Elimina', - 'ok' => 'OK', + 'ok' => 'OK' ], 'dashboard' => [ 'menu_label' => 'Dashboard', 'widget_label' => 'Widget', 'widget_width' => 'Larghezza', + 'full_width' => 'intera larghezza', 'add_widget' => 'Aggiungi widget', 'widget_inspector_title' => 'Configurazione widget', 'widget_inspector_description' => 'Configura il widget', @@ -61,39 +68,50 @@ return [ 'status' => [ 'widget_title_default' => 'Stato del sistema', 'online' => 'online', - 'update_available' => '{0} aggiornamenti disponibili!|{1} aggiornamento disponibile!|[2,Inf] aggiornamenti disponibili!', + 'maintenance' => 'in manutenzione', + 'update_available' => '{0} aggiornamenti disponibili!|{1} aggiornamento disponibile!|[2,Inf] aggiornamenti disponibili!' ] ], 'user' => [ - 'name' => 'Amministratori', + 'name' => 'Amministratore', 'menu_label' => 'Amministratori', 'menu_description' => 'Gestisci gli utenti amministratori, i gruppi e le autorizzazioni.', 'list_title' => 'Gestisci amministratori', - 'new' => 'Nuovo amministratorre', - 'login' => "Login", - 'first_name' => "Nome", - 'last_name' => "Cognome", - 'full_name' => "Nome completo", - 'email' => "Indirizzo e-mail", - 'groups' => "Gruppi", - 'groups_comment' => "Seleziona i gruppi a cui appartiene l'utente.", - 'avatar' => "Avatar", - 'password' => "Password", - 'password_confirmation' => "Conferma password", - 'superuser' => "Super User", - 'superuser_comment' => "Seleziona per consentire all'utente di accedere a tutte le aree.", + 'new' => 'Nuovo amministratore', + 'login' => 'Login', + 'first_name' => 'Nome', + 'last_name' => 'Cognome', + 'full_name' => 'Nome completo', + 'email' => 'Indirizzo e-mail', + 'groups' => 'Gruppi', + 'groups_comment' => 'Seleziona i gruppi a cui appartiene l\'utente.', + 'avatar' => 'Avatar', + 'password' => 'Password', + 'password_confirmation' => 'Conferma password', + 'permissions' => 'Autorizzazioni', + 'account' => 'Account', + 'superuser' => 'Super User', + 'superuser_comment' => 'Seleziona per consentire all\'utente di accedere a tutte le aree.', 'send_invite' => 'Invia invito tramite e-mail', - 'send_invite_comment' => 'Seleziona per inviare un invito all\'utente tramite e-mail', + 'send_invite_comment' => 'Invia un messaggio di benvenuto contenente le credenziali per l\'accesso.', 'delete_confirm' => 'Vuoi davvero eliminare questo amministratore?', 'return' => 'Ritorna alla lista degli amministratori', + 'allow' => 'Consenti', + 'inherit' => 'Eredita', + 'deny' => 'Nega', 'group' => [ 'name' => 'Gruppo', 'name_field' => 'Nome', + 'description_field' => 'Descrizione', + 'is_new_user_default_field' => 'Aggiungi i nuovi amministratori a questo gruppo per impostazione predefinita.', + 'code_field' => 'Codice', + 'code_comment' => 'Inserisci un codice univoco se vuoi accedere a questo elementro tramite API.', 'menu_label' => 'Gruppi', 'list_title' => 'Gestisci gruppi', - 'new' => 'Nuovo gruppo amministratore', + 'new' => 'Nuovo gruppo', 'delete_confirm' => 'Vuoi davvero eliminare questo gruppo amministratore?', 'return' => 'Ritorna alla lista dei gruppi', + 'users_count' => 'Utenti' ], 'preferences' => [ 'not_authenticated' => 'Non c\'è nessun utente autenticato per cui caricare o salvare le preferenze.' @@ -110,30 +128,56 @@ return [ 'behavior_not_ready' => 'L\'elenco non è stato inizializzato, controlla di aver chiamato il metodo makeLists() nel controller.', 'invalid_column_datetime' => "Il valore della colonna ':column' non è un oggetto di tipo DateTime, hai dimenticato un riferimento a \$dates nel modello?", 'pagination' => 'Record visualizzati: :from-:to di :total', + 'prev_page' => 'Pagina precedente', + 'next_page' => 'Pagina successiva', + 'loading' => 'Caricamento...', 'setup_title' => 'Configura elenco', 'setup_help' => 'Utilizza le checkbox per selezionare le colonne che vuoi visualizzare nell\'elenco. Puoi cambiare la posizione delle colonne trascinandole verso l\'alto o il basso.', 'records_per_page' => 'Record per pagina', - 'records_per_page_help' => 'Seleziona il numero di record da visualizzare su ogni pagina. Ricorda che un numero elevato di record in una singola pagina può ridurre le prestazioni.' + 'records_per_page_help' => 'Seleziona il numero di record da visualizzare su ogni pagina. Ricorda che un numero elevato di record in una singola pagina può ridurre le prestazioni.', + 'delete_selected' => 'Elimina selezionati', + 'delete_selected_empty' => 'Non hai selezionato nessun record da eliminare.', + 'delete_selected_confirm' => 'Elimina i record selezionati?', + 'delete_selected_success' => 'I record selezionati sono stati eliminati con successo.' + ], + 'fileupload' => [ + 'attachment' => 'Allegato', + 'help' => 'Aggiungi un titolo e una descrizione per questo allegato.', + 'title_label' => 'Titolo', + 'description_label' => 'Descrizione', + 'default_prompt' => 'Fai clic su %s o trascina un file qui per eseguire il caricamento', + 'attachment_url' => 'URL Allegato', + 'upload_file' => 'Carica file', + 'upload_error' => 'Errore nel caricamento', + 'remove_confirm' => 'Sei sicuro?', + 'remove_file' => 'Rimuovi file' ], 'form' => [ - 'create_title' => "Nuovo :name", - 'update_title' => "Modifica :name", - 'preview_title' => "Anteprima :name", + 'create_title' => 'Crea :name', + 'update_title' => 'Modifica :name', + 'preview_title' => 'Anteprima :name', 'create_success' => ':name creato con successo', 'update_success' => ':name modificato con successo', 'delete_success' => ':name eliminato con successo', - 'missing_id' => "L'ID del record non è stato specificato.", + 'missing_id' => 'L\'ID del record non è stato specificato.', 'missing_model' => 'Il form utilizzato nella classe :class non ha un modello definito.', 'missing_definition' => "Il form non contiene il campo ':field'.", - 'not_found' => 'Nessun record per l\'ID :id è stato trovato.', + 'not_found' => 'Nessun record con ID :id è stato trovato.', + 'action_confirm' => 'Sei sicuro?', 'create' => 'Crea', 'create_and_close' => 'Crea e chiudi', 'creating' => 'Creazione in corso...', + 'creating_name' => 'Creazione :name in corso...', 'save' => 'Salva', 'save_and_close' => 'Salva e chiudi', 'saving' => 'Salvataggio in corso...', + 'saving_name' => 'Salvataggio :name in corso...', 'delete' => 'Elimina', 'deleting' => 'Eliminazione in corso...', + 'deleting_name' => 'Eliminazione :name in corso...', + 'reset_default' => 'Ripristina predefiniti', + 'resetting' => 'Ripristino in corso', + 'resetting_name' => 'Ripristino :name in corso', 'undefined_tab' => 'Varie', 'field_off' => 'Off', 'field_on' => 'On', @@ -141,44 +185,71 @@ return [ 'apply' => 'Applica', 'cancel' => 'Annulla', 'close' => 'Chiudi', + 'confirm' => 'Conferma', + 'reload' => 'Ricarica', + 'complete' => 'Completo', 'ok' => 'OK', 'or' => 'o', 'confirm_tab_close' => 'Vuoi davvero chiudere il tab? Le modifiche non salvate andranno perse.', 'behavior_not_ready' => 'Il form non è stato inizializzato, verifica di aver chiamato il metodo initForm() nel controller.', - 'preview_no_files_message' => 'I file non sono stati caricati', + 'preview_no_files_message' => 'Non ci sono file caricati.', + 'preview_no_record_message' => 'Nessun record selezionato.', 'select' => 'Seleziona', 'select_all' => 'tutti', 'select_none' => 'nessuno', + 'select_placeholder' => 'seleziona', + 'insert_row' => 'Inserisci riga', + 'delete_row' => 'Elimina riga', + 'concurrency_file_changed_title' => 'Il file è stato cambiato', + 'concurrency_file_changed_description' => "Il file che stavi modificando è stato cambiato da un altro utente. Puoi ricaricare il file e perdere le tue modifiche oppure sovrascrivere il file sul disco." ], 'relation' => [ + 'missing_config' => "La relazione non ha nessuna configurazione per ':config'.", 'missing_definition' => "La relazione non contiene una definizione per il campo ':field'.", - 'missing_model' => "La relazione utilizzata nella classe :class non ha un modello definito.", - 'invalid_action_single' => "L'azione non può essere eseguita su una relazione singola.", - 'invalid_action_multi' => "L'azione non può essere eseguita su una relazione multipla.", - 'add' => "Aggiungi", - 'add_name' => "Aggiungi :name", - 'create' => "Crea", - 'create_name' => "Crea :name", - 'update' => "Aggiorna", - 'update_name' => "Aggiorna :name", - 'remove' => "Rimuovi", - 'remove_name' => "Rimuovi :name", - 'delete' => "Elimina", - 'delete_name' => "Elimina :name", + 'missing_model' => 'La relazione utilizzata nella classe :class non ha un modello definito.', + 'invalid_action_single' => 'L\'azione non può essere eseguita su una relazione singola.', + 'invalid_action_multi' => 'L\'azione non può essere eseguita su una relazione multipla.', + 'help' => 'Fai clic su un elemento per aggiungere', + 'related_data' => 'Dati :name correlati', + 'add' => 'Aggiungi', + 'add_selected' => 'Aggiungi selezionati', + 'add_a_new' => 'Aggiungi nuovo :name', + 'link_selected' => 'Collega selezionati', + 'link_a_new' => 'Collega nuovo :name', + 'cancel' => 'Annulla', + 'close' => 'Chiudi', + 'add_name' => 'Aggiungi :name', + 'create' => 'Crea', + 'create_name' => 'Crea :name', + 'update' => 'Aggiorna', + 'update_name' => 'Aggiorna :name', + 'preview' => 'Visualizza', + 'preview_name' => 'Visualizza :name', + 'remove' => 'Rimuovi', + 'remove_name' => 'Rimuovi :name', + 'delete' => 'Elimina', + 'delete_name' => 'Elimina :name', + 'delete_confirm' => 'Sei sicuro?', + 'link' => 'Collega', + 'link_name' => 'Collega :name', + 'unlink' => 'Scollega', + 'unlink_name' => 'Scollega :name', + 'unlink_confirm' => 'Sei sicuro?' ], 'model' => [ - 'name' => "Modello", - 'not_found' => "Nessun modello di ':class' con l'ID :id trovato.", - 'missing_id' => "Nessun ID specificato.", + 'name' => 'Modello', + 'not_found' => "Nessun modello ':class' con ID :id trovato.", + 'missing_id' => 'Nessun ID specificato per la ricerca.', 'missing_relation' => "Il modello ':class' non contiene una definizione per la relazione ':relation'.", - 'invalid_class' => "Il modello :model utilizzato nella classe :class non è valido, deve ereditare la classe Model.", + 'missing_method' => "Il modello ':class' non contiene un metodo ':method'.", + 'invalid_class' => "Il modello :model utilizzato nella classe :class non è valido, deve ereditare la classe \Model.", 'mass_assignment_failed' => "Assegnazione massiva fallita per l'attributo ':attribute' del modello.", ], 'warnings' => [ - 'tips' => 'Suggerimenti di configurazione del sistema', + 'tips' => 'Suggerimenti per la configurazione del sistema', 'tips_description' => 'Ci sono elementi a cui è necessario prestare attenzione al fine di configurare il sistema in maniera corretta.', 'permissions' => 'La cartella :name o le sue sottocartelle non sono scrivibili da PHP. Imposta le corrette autorizzazioni per il server web su questa cartella.', - 'extension' => 'L\'estenzione di PHP :name non è installata. Installa questa libreria ed attiva l\'estensione.' + 'extension' => 'L\'estensione di PHP :name non è installata. Installa questa libreria ed attiva l\'estensione.' ], 'editor' => [ 'menu_label' => 'Preferenze editor di codice', @@ -191,23 +262,41 @@ return [ 'highlight_active_line' => 'Evidenzia la linea attiva', 'show_invisibles' => 'Mostra caratteri invisibili', 'show_gutter' => 'Visualizza numeri di linea', - 'theme' => 'Schema di colori', + 'theme' => 'Schema di colori' ], 'tooltips' => [ 'preview_website' => 'Anteprima del sito web' ], 'mysettings' => [ 'menu_label' => 'Impostazioni personali', - 'menu_description' => 'Impostazioni legate al tuo account amministratore', + 'menu_description' => 'Impostazioni legate al tuo account amministratore' ], 'myaccount' => [ 'menu_label' => 'Il mio account', 'menu_description' => 'Aggiorna i dettagli del tuo account, come il nome, l\'indirizzo e-mail e la password.', 'menu_keywords' => 'sicurezza login' ], + 'branding' => [ + 'menu_label' => 'Personalizza pannello di controllo', + 'menu_description' => 'Personalizza l\'area di amministrazione, come il nome, i colori ed il logo.', + 'brand' => 'Marchio', + 'logo' => 'Logo', + 'logo_description' => 'Carica un logo personalizzato da utilizzare nel pannello di controllo.', + 'app_name' => 'Nome dell\'applicazione', + 'app_name_description' => 'Questo campo verrà visualizzato nella barra del titolo del pannello di controllo.', + 'app_tagline' => 'Slogan dell\'applicazione', + 'app_tagline_description' => 'Questo campo verrà visualizzato nella schermata di login del pannello di controllo.', + 'colors' => 'Colori', + 'primary_light' => 'Principale (Chiaro)', + 'primary_dark' => 'Principale (Scuro)', + 'secondary_light' => 'Secondario (Chiaro)', + 'secondary_dark' => 'Secondario (Scuro)', + 'styles' => 'Stili', + 'custom_stylesheet' => 'Foglio di stile personalizzato' + ], 'backend_preferences' => [ 'menu_label' => 'Preferenze pannello di controllo', - 'menu_description' => 'Gestisci le preferenze della lingua e l\'aspetto del pannello di controllo.', + 'menu_description' => 'Gestisci le preferenze del tuo account, come la lingua.', 'locale' => 'Lingua', 'locale_comment' => 'Seleziona la lingua da utilizzare.', ], @@ -222,4 +311,7 @@ return [ 'last_name' => 'Cognome', 'email' => 'Indirizzo e-mail', ], + 'filter' => [ + 'all' => 'tutto' + ] ]; diff --git a/modules/backend/lang/pl/lang.php b/modules/backend/lang/pl/lang.php index 3851b4e50..b692adc9c 100644 --- a/modules/backend/lang/pl/lang.php +++ b/modules/backend/lang/pl/lang.php @@ -19,7 +19,7 @@ return [ 'help' => "Nie posiadasz odpowiednich uprawnień, aby zobaczyć tą stronę.", 'cms_link' => 'Powrót do panelu back-end' ], - 'invalid_token' => [ + 'invalid_token' => [ 'label' => 'Nieprawidłowy żeton bezpieczeństwa' ] ], @@ -82,14 +82,14 @@ return [ 'first_name' => 'Imię', 'last_name' => 'Nazwisko', 'full_name' => 'Pełna nazwa', - 'email' => 'Email', + 'email' => 'E-mail', 'groups' => 'Grupa', 'groups_comment' => 'Określ, do której grupy należy ten użytkownik', - 'avatar' => 'Avatar', + 'avatar' => 'Awatar', 'password' => 'Hasło', 'password_confirmation' => 'Potwierdź hasło', 'permissions' => 'Uprawnienia', - 'account' => 'Konto', + 'account' => 'Konto', 'superuser' => 'Super Użytkownik', 'superuser_comment' => 'Zaznacz to pole jeżeli chcesz zezwolić temu użytkownikowi na pełny dostęp do panelu.', 'send_invite' => 'Wyślij zaproszenie wiadomością email', @@ -111,7 +111,7 @@ return [ 'new' => 'Nowa grupa Administratorów', 'delete_confirm' => 'Jesteś pewny, że chcesz usunąć tą grupę administratorów?', 'return' => 'Wróć do listy grup', - 'users_count' => 'Użytkowników' + 'users_count' => 'Użytkowników' ], 'preferences' => [ 'not_authenticated' => 'Nie znaleziono uwierzytelnionego użytkownika, aby załadować lub zapisać ustawienia.' @@ -135,7 +135,7 @@ return [ 'setup_help' => 'Użyj pól wyboru, aby wybrać kolumny, które chcesz zobaczyć w liście. Możesz zmienić pozycję kolumny przeciągająć ją w dół lub w górę.', 'records_per_page' => 'Rekordy na stronę', 'records_per_page_help' => 'Wybierz liczbnę rekordów do wyświetlenia na stronę. Wyższa liczba rekordów na jedną stronę może zmniejszyć wydajność.', - 'delete_selected' => 'Usuń zaznaczone', + 'delete_selected' => 'Usuń zaznaczone', 'delete_selected_empty' => 'Nie wybrano elementów do usunięcia.', 'delete_selected_confirm' => 'Usunąć zaznaczone elementy?', 'delete_selected_success' => 'Pomyślnie usunięto zaznaczone elementy.' @@ -145,7 +145,7 @@ return [ 'help' => 'Dodaj tytuł oraz opis załącznika.', 'title_label' => 'Tytuł', 'description_label' => 'Opis', - 'default_prompt' => 'Kliknij %s lub upuść plik aby przesłać', + 'default_prompt' => 'Kliknij %s lub upuść plik aby przesłać', 'attachment_url' => 'URL załącznika', 'upload_file' => 'Prześlij plik', 'upload_error' => 'Błąd przesyłania', @@ -192,7 +192,7 @@ return [ 'confirm_tab_close' => 'Czy naprawdę chcesz zamknąć tą kartę? Wszystkie niezapisane zmiany zostaną utracone.', 'behavior_not_ready' => 'Zachowanie formularza nie zostało zainicjowane, sprawdź czy wywołałeś initForm() w swoim kontrolerze.', 'preview_no_files_message' => 'Brak wgranych plików.', - 'preview_no_record_message' => 'Break zaznaczonych elementów.', + 'preview_no_record_message' => 'Break zaznaczonych elementów.', 'select' => 'Zaznacz', 'select_all' => 'wszystkie', 'select_none' => 'żadne', @@ -203,7 +203,7 @@ return [ 'concurrency_file_changed_description' => "Plik, który edytujesz został zmieniony na dysku przez innego użytkownika. Możesz przeładować plik i stracić swoje zmiany lub nadpisać plik na dysku." ], 'relation' => [ - 'missing_config' => "Zachowanie relacji nie zawiera konfiguracji dla pola ':config'.", + 'missing_config' => "Zachowanie relacji nie zawiera konfiguracji dla pola ':config'.", 'missing_definition' => "Zachowanie relacji nie zawiera definicji dla pola ':field'.", 'missing_model' => "Zachowanie relacji użyte w klasie :class nie zawiera definicji modelu.", 'invalid_action_single' => "Ta akcja nie może zostać wykonana na pojedynczej zależności.", @@ -213,7 +213,7 @@ return [ 'add' => "Dodaj", 'add_selected' => "Dodaj zaznaczony", 'add_a_new' => "Dodaj nowy :name", - 'link_selected' => 'Dołącz zaznaczone', + 'link_selected' => 'Dołącz zaznaczone', 'link_a_new' => 'Dołącz nowy :name', 'cancel' => "Anuluj", 'close' => "Zamknij", @@ -229,7 +229,7 @@ return [ 'delete' => "Skasuj", 'delete_name' => "Skasuj :name", 'delete_confirm' => "Na pewno?", - 'link' => 'Dołącz', + 'link' => 'Dołącz', 'link_name' => 'Dołącz :name', 'unlink' => 'Odłącz', 'unlink_name' => 'Odłącz :name', @@ -252,13 +252,14 @@ return [ ], 'editor' => [ 'menu_label' => 'Ustawienia edytora kodu', - 'menu_description' => 'Personalizuj ustawienia edytora kodu, takie jak wielkość fontu oraz kolorostyka.', - 'font_size' => 'Wielkość fontu', + 'menu_description' => 'Personalizuj ustawienia edytora kodu, takie jak wielkość czcionki oraz kolorostyka.', + 'font_size' => 'Wielkość czcionki', 'tab_size' => 'Wielkość karty', 'use_hard_tabs' => 'Wcięcie tabulaturą', 'code_folding' => 'Zawijanie kodu', 'word_wrap' => 'Zawijanie wierszy', 'highlight_active_line' => 'Podświetl aktywne linie', + 'auto_closing' => 'Automatycznie zamykaj tagi i specjalne znaki', 'show_invisibles' => 'Pokaż niewidzialne znaki', 'show_gutter' => 'Pokaż gutter', 'theme' => 'Schemat kolorów' @@ -311,6 +312,6 @@ return [ 'email' => 'Email' ], 'filter' => [ - 'all' => 'wszystkie' + 'all' => 'wszystkie' ] ]; diff --git a/modules/backend/lang/ro/lang.php b/modules/backend/lang/ro/lang.php index dede7394d..8728f30cb 100644 --- a/modules/backend/lang/ro/lang.php +++ b/modules/backend/lang/ro/lang.php @@ -191,6 +191,7 @@ return [ 'code_folding' => 'Code folding', 'word_wrap' => 'Word wrap', 'highlight_active_line' => 'Evidentiere linie activa', + 'auto_closing' => 'Inchide automat tag-uri si caractere speciale', 'show_invisibles' => 'Arata caractere invizibile', 'show_gutter' => 'Afiseaza panou', 'theme' => 'Schema culori', diff --git a/modules/backend/lang/zh-tw/lang.php b/modules/backend/lang/zh-tw/lang.php new file mode 100644 index 000000000..c066d9eb2 --- /dev/null +++ b/modules/backend/lang/zh-tw/lang.php @@ -0,0 +1,305 @@ + [ + 'title' => '管理介面' + ], + 'field' => [ + 'invalid_type' => '錯誤的字串類型 :type', + 'options_method_not_exists' => "模型 :model 必須定義一個返回 ':field' 表單字串選項的方法 :method()。" + ], + 'widget' => [ + 'not_registered' => "元件 ':name' 還沒註冊", + 'not_bound' => "元件 ':name' 沒綁到控制器" + ], + 'page' => [ + 'untitled' => '未命名', + 'access_denied' => [ + 'label' => '拒絕訪問', + 'help' => "您沒有訪問這個頁面需要的權限.", + 'cms_link' => '返回管理介面' + ] + ], + 'partial' => [ + 'not_found_name' => "元件 ':name' 找不到." + ], + 'account' => [ + 'sign_out' => '登出', + 'login' => '登入', + 'reset' => '重置', + 'restore' => '還原', + 'login_placeholder' => '登入', + 'password_placeholder' => '密碼', + 'forgot_password' => '忘記您的密碼?', + 'enter_email' => '輸入您的email', + 'enter_login' => '輸入帳號', + 'email_placeholder' => 'email', + 'enter_new_password' => '輸入新密碼', + 'password_reset' => '密碼重置', + 'restore_success' => '密碼重置的郵件已發送到您的電子信箱', + 'restore_error' => "找不到使用者 ':login'", + 'reset_success' => '您的密碼已經重置成功. 您現在可以登入了', + 'reset_error' => '密碼重置失敗. 請重試!', + 'reset_fail' => '不能重置您的密碼!', + 'apply' => '套用', + 'cancel' => '取消', + 'delete' => '刪除', + 'ok' => 'OK' + ], + 'dashboard' => [ + 'menu_label' => '儀表板', + 'widget_label' => '元件', + 'widget_width' => '寬度', + 'full_width' => '全部寬度', + 'add_widget' => '新增元件', + 'widget_inspector_title' => '元件設定', + 'widget_inspector_description' => '設定報表元件', + 'widget_columns_label' => '寬度 :columns', + 'widget_columns_description' => '元件寬度, 1 到 10', + 'widget_columns_error' => '請輸入元件寬度, 1 到 10', + 'columns' => '{1} 欄|[2,Inf] 欄', + 'widget_new_row_label' => '強制新列', + 'widget_new_row_description' => '把元件放到新列', + 'widget_title_label' => '元件標題', + 'widget_title_error' => '需要元件標題', + 'status' => [ + 'widget_title_default' => '系統狀態', + 'online' => '在線', + 'maintenance' => '維護中', + 'update_available' => '{0} 更新可用!|{1} 更新可用!|[2,Inf] 更新可用!' + ] + ], + 'user' => [ + 'name' => '管理員', + 'menu_label' => '管理員', + 'menu_description' => '管理管理介面管理員使用者, 群組和權限', + 'list_title' => '管理', + 'new' => '新管理員', + 'login' => '登入', + 'first_name' => '名', + 'last_name' => '姓', + 'full_name' => '全名', + 'email' => '郵件', + 'groups' => '團隊', + 'groups_comment' => '指定這個人屬於哪個群組', + 'avatar' => '頭像', + 'password' => '密碼', + 'password_confirmation' => '確認密碼', + 'permissions' => '權限', + 'account' => '帳號', + 'superuser' => '超級使用者', + 'superuser_comment' => '選取並允許這個人訪問全部區域', + 'send_invite' => '發送邀請郵件', + 'send_invite_comment' => '發送一封包含使用者名和密碼的歡迎郵件', + 'delete_confirm' => '您真的想要刪除這個管理員?', + 'return' => '返回管理員列表', + 'allow' => '允許', + 'inherit' => '繼承', + 'deny' => '拒絕', + 'group' => [ + 'name' => '群組', + 'name_field' => '名字', + 'description_field' => '描述', + 'is_new_user_default_field' => '預設增加新管理員到這個群組', + 'code_field' => '代碼', + 'code_comment' => '如果您想訪問 API, 請輸入唯一碼', + 'menu_label' => '群組', + 'list_title' => '管理群組', + 'new' => '新管理群組', + 'delete_confirm' => '您真的想要刪除這個管理群組?', + 'return' => '返回群組列表', + ], + 'preferences' => [ + 'not_authenticated' => '沒有認證使用者載入或儲存設定' + ] + ], + 'list' => [ + 'default_title' => '列表', + 'search_prompt' => '搜尋...', + 'no_records' => '目前頁面中沒有記錄', + 'missing_model' => ':class 中的列表沒有定義好的模型。', + 'missing_column' => '沒有 :columns 的欄定義', + 'missing_columns' => ':class 中使用的列表沒有定義好的欄', + 'missing_definition' => "列表不包含 ':field' 欄.", + 'behavior_not_ready' => '列表沒有初始化, 確認您的控制器中調用了makeLists()', + 'invalid_column_datetime' => "欄值 ':column' 不是時間對象, 缺少了 \$dates 在模型中的引用嗎?", + 'pagination' => '顯示記錄: :from-:to :total', + 'prev_page' => '之前頁', + 'next_page' => '下一頁', + 'loading' => '載入中...', + 'setup_title' => '建立列表', + 'setup_help' => '使用多選框選擇您想在列表中看到的欄. 您可以通過拖拽調整欄的位置', + 'records_per_page' => '每頁的記錄', + 'records_per_page_help' => '選擇每頁想顯示的記錄數量. 請注意一頁中太多記錄可能會降低性能', + 'delete_selected' => '刪除選擇的', + 'delete_selected_empty' => '沒有需要刪除的記錄', + 'delete_selected_confirm' => '刪除選取的記錄?', + 'delete_selected_success' => '成功刪除選擇的記錄', + ], + 'fileupload' => [ + 'attachment' => '附件', + 'help' => '給附件新增標題和描述', + 'title_label' => '標題', + 'description_label' => '描述' + ], + 'form' => [ + 'create_title' => '新 :name', + 'update_title' => '編輯 :name', + 'preview_title' => '預覽 :name', + 'create_success' => ':name 建立成功', + 'update_success' => ':name 更新成功', + 'delete_success' => ':name 刪除成功', + 'missing_id' => '表單記錄ID沒有指定', + 'missing_model' => ':class 中使用的表單沒有定義的model', + 'missing_definition' => "表單不包含字串 ':field'.", + 'not_found' => '表單 ID :id 找不到', + 'action_confirm' => '您確定?', + 'create' => '建立', + 'create_and_close' => '建立和關閉', + 'creating' => '建立中...', + 'creating_name' => '建立 :name...', + 'save' => '儲存', + 'save_and_close' => '儲存和關閉', + 'saving' => '儲存...', + 'saving_name' => '儲存 :name...', + 'delete' => '刪除', + 'deleting' => '刪除中...', + 'deleting_name' => '刪除 :name...', + 'reset_default' => '重置到預設', + 'resetting' => '重置', + 'resetting_name' => '重置 :name', + 'undefined_tab' => '雜項', + 'field_off' => '關', + 'field_on' => '開', + 'add' => '增加', + 'apply' => '應用', + 'cancel' => '取消', + 'close' => '關閉', + 'confirm' => '確認', + 'reload' => '重新載入', + 'ok' => 'OK', + 'or' => '或', + 'confirm_tab_close' => '您真的想要關閉這個標籤嗎? 未儲存的改變會丟失', + 'behavior_not_ready' => '表單還沒初始化, 確保您調用了控制器中的 initForm()', + 'preview_no_files_message' => '檔案沒有上傳', + 'select' => '選擇', + 'select_all' => 'all', + 'select_none' => 'none', + 'select_placeholder' => '請選擇', + 'insert_row' => '插入行', + 'delete_row' => '刪除行', + 'concurrency_file_changed_title' => '檔案異動', + 'concurrency_file_changed_description' => "您正在編輯的檔案正在被其他使用者修改. 您可以重新載入或覆蓋硬碟上的檔案." + ], + 'relation' => [ + 'missing_config' => "關聯沒有':config'的設定檔案.", + 'missing_definition' => "關聯不包含 ':field' 的定義.", + 'missing_model' => "用於 :class 的關聯沒有定義好的model.", + 'invalid_action_single' => "這個操作不能在單一關聯上執行.", + 'invalid_action_multi' => "這個操作不能在多重關聯上執行.", + 'help' => "點選增加", + 'related_data' => "相關的 :name", + 'add' => "增加", + 'add_selected' => "增加選取的", + 'add_a_new' => "增加一個新的 :name", + 'link_selected' => "關聯選取", + 'link_a_new' => "關聯一個新的 :name", + 'cancel' => "取消", + 'close' => "關閉", + 'add_name' => "增加 :name", + 'create' => "建立", + 'create_name' => "建立 :name", + 'update' => "更新", + 'update_name' => "更新 :name", + 'preview' => "預覽", + 'preview_name' => "預覽 :name", + 'remove' => "移除", + 'remove_name' => "移除 :name", + 'delete' => "刪除", + 'delete_name' => "刪除 :name", + 'delete_confirm' => "您確定?", + 'link' => "關聯", + 'link_name' => "關聯 :name", + 'unlink' => "取消關聯", + 'unlink_name' => "取消關聯 :name", + 'unlink_confirm' => "您確定?", + ], + 'model' => [ + 'name' => 'Model', + 'not_found' => "Model ':class' ID :id 找不到", + 'missing_id' => '沒有指定的ID搜尋model記錄', + 'missing_relation' => "Model ':class' 不包含 ':relation'.", + 'missing_method' => "Model ':class' 不包含 ':method'.", + 'invalid_class' => "Model :model 在 :class 中是錯誤的, 必須繼承 \\Model class.", + 'mass_assignment_failed' => "針對Model屬性':attribute'的大量賦值失敗." + ], + 'warnings' => [ + 'tips' => '系統設定技巧', + 'tips_description' => '您需要注意那些issue, 以使系統設定正確', + 'permissions' => '目錄 :name 或子目錄對PHP不可寫. 請對這個目錄上的webserver設定正確的權限', + 'extension' => 'PHP外掛 :name 沒安裝. 請安裝這個庫並且啟用外掛' + ], + 'editor' => [ + 'menu_label' => '代碼編輯器選項', + 'menu_description' => '自訂代碼編輯器選項, 例如字體大小和顏色主題', + 'font_size' => '字體大小', + 'tab_size' => '標籤大小', + 'use_hard_tabs' => '使用tabs縮進', + 'code_folding' => '代碼摺疊', + 'word_wrap' => '自動換行', + 'highlight_active_line' => '醒目顯示操作中的行', + 'show_invisibles' => '顯示隱藏字元', + 'show_gutter' => '顯示gutter', + 'theme' => '色彩主題' + ], + 'tooltips' => [ + 'preview_website' => '預覽網站' + ], + 'mysettings' => [ + 'menu_label' => '我的設定', + 'menu_description' => '設定涉及到您的管理帳號' + ], + 'myaccount' => [ + 'menu_label' => '我的帳號', + 'menu_description' => '更新您的帳號細節, 例如名字, 郵件地址和密碼', + 'menu_keywords' => '安全登入' + ], + 'branding' => [ + 'menu_label' => '自訂管理介面', + 'menu_description' => '自訂管理區域, 例如名字, 顏色和logo', + 'brand' => '品牌', + 'logo' => 'Logo', + 'logo_description' => '上傳自訂logo到管理介面', + 'app_name' => '網站名稱', + 'app_name_description' => '這個名稱顯示在管理介面的標題區域', + 'app_tagline' => '網站標語', + 'app_tagline_description' => '標語顯示在管理介面的登入介面', + 'colors' => '顏色', + 'primary_light' => '主要 (Light)', + 'primary_dark' => '主要 (Dark)', + 'secondary_light' => '次要 (Light)', + 'secondary_dark' => '次要 (Dark)', + 'styles' => '樣式', + 'custom_stylesheet' => '自訂樣式' + ], + 'backend_preferences' => [ + 'menu_label' => '管理介面設定', + 'menu_description' => '管理您的管理介面設定, 例如希望使用的語言。', + 'locale' => '語言', + 'locale_comment' => '選擇您希望使用的本地語言。' + ], + 'access_log' => [ + 'hint' => '這個log顯示了管理員成功登入的訊息. 記錄保持:days天。', + 'menu_label' => '訪問日誌', + 'menu_description' => '查看成功登入管理介面使用者日誌。', + 'created_at' => '日期 & 時間', + 'login' => '登入', + 'ip_address' => 'IP地址', + 'first_name' => '名', + 'last_name' => '姓', + 'email' => 'Email' + ], + 'filter' => [ + 'all' => '全部' + ] +]; \ No newline at end of file diff --git a/modules/backend/layouts/_mainmenu.htm b/modules/backend/layouts/_mainmenu.htm index 216d7c960..35ae18eb8 100644 --- a/modules/backend/layouts/_mainmenu.htm +++ b/modules/backend/layouts/_mainmenu.htm @@ -2,28 +2,26 @@ $activeItem = BackendMenu::getActiveMainMenuItem(); $mySettings = System\Classes\SettingsManager::instance()->listItems('mysettings'); ?> -