From 4ad4dfa55ae75e3e4ebd0537a44c5d0c758636cc Mon Sep 17 00:00:00 2001 From: Christopher Wilkinson Date: Fri, 27 Sep 2019 00:45:10 +0100 Subject: [PATCH 001/197] Show bookshelves that a book belongs to on a book view Closes #1598 --- app/Entities/Repos/EntityRepo.php | 11 ++++++++++ app/Http/Controllers/BookController.php | 2 ++ resources/lang/en/entities.php | 1 + resources/views/books/show.blade.php | 13 +++++++++--- tests/Entity/BookShelfTest.php | 28 +++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/app/Entities/Repos/EntityRepo.php b/app/Entities/Repos/EntityRepo.php index 13a335ea0..0dd0fbb0a 100644 --- a/app/Entities/Repos/EntityRepo.php +++ b/app/Entities/Repos/EntityRepo.php @@ -413,6 +413,17 @@ class EntityRepo return collect($tree); } + + /** + * Get the bookshelves that a book is contained in. + * @param Book $book + * @return \Illuminate\Database\Eloquent\Collection|static[] + */ + public function getBookParentShelves(Book $book) + { + return $this->permissionService->enforceEntityRestrictions('shelf', $book->shelves())->get(); + } + /** * Get the child items for a chapter sorted by priority but * with draft items floated to the top. diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php index a9a24d2ff..35f62012a 100644 --- a/app/Http/Controllers/BookController.php +++ b/app/Http/Controllers/BookController.php @@ -150,6 +150,7 @@ class BookController extends Controller $this->checkOwnablePermission('book-view', $book); $bookChildren = $this->bookRepo->getBookChildren($book); + $bookParentShelves = $this->bookRepo->getBookParentShelves($book); Views::add($book); if ($request->has('shelf')) { @@ -161,6 +162,7 @@ class BookController extends Controller 'book' => $book, 'current' => $book, 'bookChildren' => $bookChildren, + 'bookParentShelves' => $bookParentShelves, 'activity' => Activity::entityActivity($book, 20, 1) ]); } diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index 6bbc723b0..79e640378 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -135,6 +135,7 @@ return [ 'books_sort_chapters_last' => 'Chapters Last', 'books_sort_show_other' => 'Show Other Books', 'books_sort_save' => 'Save New Order', + 'book_parent_shelves_empty' => 'Shelves that this book is on will appear here.', // Chapters 'chapter' => 'Chapter', diff --git a/resources/views/books/show.blade.php b/resources/views/books/show.blade.php index cbafdb436..41581e123 100644 --- a/resources/views/books/show.blade.php +++ b/resources/views/books/show.blade.php @@ -57,9 +57,7 @@ @stop - @section('right') -
{{ trans('common.details') }}
-
{{ trans('common.actions') }}
@@ -125,6 +122,16 @@
+
+
{{ trans('entities.shelves_long') }}
+ + @if(count($bookParentShelves) > 0) + @include('partials.entity-list', ['entities' => $bookParentShelves, 'style' => 'compact']) + @else +
{{ trans('entities.book_parent_shelves_empty') }}
+ @endif +
+ @stop @section('left') diff --git a/tests/Entity/BookShelfTest.php b/tests/Entity/BookShelfTest.php index 5c7673847..88358405f 100644 --- a/tests/Entity/BookShelfTest.php +++ b/tests/Entity/BookShelfTest.php @@ -240,4 +240,32 @@ class BookShelfTest extends TestCase $pageVisit->assertElementNotContains('.breadcrumbs', $shelf->getShortName()); } + public function test_bookshelves_show_on_book() + { + // Create shelf + $shelfInfo = [ + 'name' => 'My test shelf' . Str::random(4), + 'description' => 'Test shelf description ' . Str::random(10) + ]; + + $this->asEditor()->post('/shelves', $shelfInfo); + $shelf = Bookshelf::where('name', '=', $shelfInfo['name'])->first(); + + // Create book and add to shelf + $this->asEditor()->post($shelf->getUrl('/create-book'), [ + 'name' => 'Test book name', + 'description' => 'Book in shelf description' + ]); + + $newBook = Book::query()->orderBy('id', 'desc')->first(); + + $resp = $this->asEditor()->get($newBook->getUrl()); + $resp->assertSee($shelfInfo['name']); + + // Remove shelf + $this->delete($shelf->getUrl()); + + $resp = $this->asEditor()->get($newBook->getUrl()); + $resp->assertDontSee($shelfInfo['name']); + } } From 6cd26e23a800b35a5f83df77cb723d00c70a2dec Mon Sep 17 00:00:00 2001 From: jakob Date: Wed, 30 Oct 2019 11:23:42 +0100 Subject: [PATCH 002/197] Allow toggling between grid and list view in shelf view (shelves.show) --- app/Http/Controllers/BookshelfController.php | 2 ++ resources/views/shelves/show.blade.php | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/BookshelfController.php b/app/Http/Controllers/BookshelfController.php index 57e67dc00..5c9da762f 100644 --- a/app/Http/Controllers/BookshelfController.php +++ b/app/Http/Controllers/BookshelfController.php @@ -103,6 +103,7 @@ class BookshelfController extends Controller public function show(string $slug) { $shelf = $this->bookshelfRepo->getBySlug($slug); + $view = setting()->getForCurrentUser('books_view_type', config('app.views.books')); $this->checkOwnablePermission('book-view', $shelf); Views::add($shelf); @@ -111,6 +112,7 @@ class BookshelfController extends Controller $this->setPageTitle($shelf->getShortName()); return view('shelves.show', [ 'shelf' => $shelf, + 'view' => $view, 'activity' => Activity::entityActivity($shelf, 20, 1) ]); } diff --git a/resources/views/shelves/show.blade.php b/resources/views/shelves/show.blade.php index 2212e1c1e..56df61c91 100644 --- a/resources/views/shelves/show.blade.php +++ b/resources/views/shelves/show.blade.php @@ -13,11 +13,19 @@

{!! nl2br(e($shelf->description)) !!}

@if(count($shelf->visibleBooks) > 0) -
- @foreach($shelf->visibleBooks as $book) - @include('books.list-item', ['book' => $book]) - @endforeach -
+ @if($view === 'list') +
+ @foreach($shelf->visibleBooks as $book) + @include('books.list-item', ['book' => $book]) + @endforeach +
+ @else +
+ @foreach($shelf->visibleBooks as $key => $book) + @include('books.grid-item', ['book' => $book]) + @endforeach +
+ @endif @else

@@ -87,6 +95,8 @@ @endif + @include('partials.view-toggle', ['view' => $view, 'type' => 'book']) +
@if(userCan('bookshelf-update', $shelf)) From 12a9a45747f3ce3ff58464cd7ccb88f2c42438e8 Mon Sep 17 00:00:00 2001 From: benrubson <6764151+benrubson@users.noreply.github.com> Date: Sun, 9 Feb 2020 10:01:33 +0100 Subject: [PATCH 003/197] Log failed accesses --- app/Http/Controllers/Auth/LoginController.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index ea584a3b6..75ade74e7 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -101,6 +101,9 @@ class LoginController extends Controller $this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); + // Also log some error message + $this->logFailedAccess($request); + return $this->sendLockoutResponse($request); } @@ -117,6 +120,9 @@ class LoginController extends Controller // user surpasses their maximum number of attempts they will get locked out. $this->incrementLoginAttempts($request); + // Also log some error message + $this->logFailedAccess($request); + return $this->sendFailedLoginResponse($request); } @@ -162,4 +168,16 @@ class LoginController extends Controller return redirect('/login'); } + /** + * Log failed accesses, matching the default fail2ban nginx/apache auth rules. + */ + protected function logFailedAccess(Request $request) + { + if (isset($_SERVER['SERVER_SOFTWARE']) && preg_match('/nginx/i', $_SERVER['SERVER_SOFTWARE'])) { + error_log('user "' . $request->get($this->username()) . '" was not found in "BookStack"', 4); + } else { + error_log('user "' . $request->get($this->username()) . '" authentication failure for "BookStack"', 4); + } + } + } From 01adf39be8fdaed911712170ded91ae878dfa254 Mon Sep 17 00:00:00 2001 From: osmansorkar Date: Wed, 19 Feb 2020 12:44:23 +0600 Subject: [PATCH 004/197] added Handle Authorization Header on .htaccess to solve Authorization problem get from laravel orginal github ripo --- public/.htaccess | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/.htaccess b/public/.htaccess index 0d55354ec..abe87b39d 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -5,6 +5,10 @@ RewriteEngine On + # Handle Authorization Header + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + # Redirect Trailing Slashes If Not A Folder... RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)/$ /$1 [L,R=301] From 1859c7917ff11230a0d364dd592c1fb325e8e40a Mon Sep 17 00:00:00 2001 From: osmansorkar Date: Sun, 23 Feb 2020 11:41:49 +0600 Subject: [PATCH 005/197] added api functionality to handle book Shelves --- .../Api/BookshelfApiController.php | 113 ++++++++++++++++++ routes/api.php | 6 + 2 files changed, 119 insertions(+) create mode 100644 app/Http/Controllers/Api/BookshelfApiController.php diff --git a/app/Http/Controllers/Api/BookshelfApiController.php b/app/Http/Controllers/Api/BookshelfApiController.php new file mode 100644 index 000000000..e6379fdec --- /dev/null +++ b/app/Http/Controllers/Api/BookshelfApiController.php @@ -0,0 +1,113 @@ + [ + 'name' => 'required|string|max:255', + 'description' => 'string|max:1000', + ], + 'update' => [ + 'name' => 'string|min:1|max:255', + 'description' => 'string|max:1000', + ], + ]; + + /** + * BookshelfApiController constructor. + * @param BookshelfRepo $bookshelfRepo + */ + public function __construct(BookshelfRepo $bookshelfRepo) + { + $this->bookshelfRepo = $bookshelfRepo; + } + + /** + * Get a listing of shelves visible to the user. + */ + public function list() + { + $shelves = Bookshelf::visible(); + return $this->apiListingResponse($shelves, [ + 'id', 'name', 'slug', 'description', 'created_at', 'updated_at', 'created_by', 'updated_by', 'image_id', + ]); + } + + /** + * Create a new shelf in the system. + * @throws ValidationException + */ + public function create(Request $request) + { + $this->checkPermission('bookshelf-create-all'); + $requestData = $this->validate($request, $this->rules['create']); + + $bookIds = $request->get('books', []); + + $shelf = $this->bookshelfRepo->create($requestData,$bookIds); + Activity::add($shelf, 'bookshelf_create', $shelf->id); + + return response()->json($shelf); + } + + /** + * View the details of a single shelf. + */ + public function read(string $id) + { + $shelf = Bookshelf::visible()->with(['tags', 'cover', 'createdBy', 'updatedBy'])->findOrFail($id); + return response()->json($shelf); + } + + /** + * Update the details of a single shelf. + * @throws ValidationException + */ + public function update(Request $request, string $id) + { + $shelf = Bookshelf::visible()->findOrFail($id); + $this->checkOwnablePermission('bookshelf-update', $shelf); + + $requestData = $this->validate($request, $this->rules['update']); + + $bookIds = $request->get('books', []); + + $shelf = $this->bookshelfRepo->update($shelf, $requestData,$bookIds); + Activity::add($shelf, 'bookshelf_update', $shelf->id); + + return response()->json($shelf); + } + + + + /** + * Delete a single shelf from the system. + * @param string $id + * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response + * @throws Exception + */ + public function delete(string $id) + { + $shelf = Bookshelf::visible()->findOrFail($id); + $this->checkOwnablePermission('bookshelf-delete', $shelf); + + $this->bookshelfRepo->destroy($shelf); + Activity::addMessage('bookshelf-delete', $shelf->name); + + return response('', 204); + } +} \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index 73f2faf79..7ca5e66fc 100644 --- a/routes/api.php +++ b/routes/api.php @@ -14,3 +14,9 @@ Route::post('books', 'BooksApiController@create'); Route::get('books/{id}', 'BooksApiController@read'); Route::put('books/{id}', 'BooksApiController@update'); Route::delete('books/{id}', 'BooksApiController@delete'); + +Route::get('shelves', 'BookshelfApiController@list'); +Route::post('shelves', 'BookshelfApiController@create'); +Route::get('shelves/{id}', 'BookshelfApiController@read'); +Route::put('shelves/{id}', 'BookshelfApiController@update'); +Route::delete('shelves/{id}', 'BookshelfApiController@delete'); \ No newline at end of file From b0610d85dac280aa36a9e76cca6df8230edd1a14 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 4 Apr 2020 00:00:19 +0100 Subject: [PATCH 006/197] Updated socialite to fix deprecated GitHub auth method - Also updated composer dependancies to cover symfony/http-foundation security issue. Fixes #1879 Related to #1989 --- composer.json | 2 +- composer.lock | 802 +++++++++++++++++++++++--------------------------- 2 files changed, 376 insertions(+), 428 deletions(-) diff --git a/composer.json b/composer.json index 0edf7bae8..6da651898 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "gathercontent/htmldiff": "^0.2.1", "intervention/image": "^2.5", "laravel/framework": "^6.12", - "laravel/socialite": "^4.2", + "laravel/socialite": "^4.3.2", "league/flysystem-aws-s3-v3": "^1.0", "onelogin/php-saml": "^3.3", "predis/predis": "^1.1", diff --git a/composer.lock b/composer.lock index c35b3f962..fd444ffa8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "309610dc13c0d46ca7553ee264a88d29", + "content-hash": "7836017e48e93254d6ff924b07f84597", "packages": [ { "name": "aws/aws-sdk-php", - "version": "3.133.6", + "version": "3.134.3", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "cd7bd2fdd159146ef6c7eeb90b73fae4fd11da57" + "reference": "3de2711a47e7c3f5e93a5c83f019188fd23f852f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/cd7bd2fdd159146ef6c7eeb90b73fae4fd11da57", - "reference": "cd7bd2fdd159146ef6c7eeb90b73fae4fd11da57", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3de2711a47e7c3f5e93a5c83f019188fd23f852f", + "reference": "3de2711a47e7c3f5e93a5c83f019188fd23f852f", "shasum": "" }, "require": { @@ -88,25 +88,25 @@ "s3", "sdk" ], - "time": "2020-01-24T19:11:35+00:00" + "time": "2020-04-03T18:11:51+00:00" }, { "name": "barryvdh/laravel-dompdf", - "version": "v0.8.5", + "version": "v0.8.6", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-dompdf.git", - "reference": "7393732b2f3a3ee357974cbb0c46c9b65b84dad1" + "reference": "d7108f78cf5254a2d8c224542967f133e5a6d4e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/7393732b2f3a3ee357974cbb0c46c9b65b84dad1", - "reference": "7393732b2f3a3ee357974cbb0c46c9b65b84dad1", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/d7108f78cf5254a2d8c224542967f133e5a6d4e8", + "reference": "d7108f78cf5254a2d8c224542967f133e5a6d4e8", "shasum": "" }, "require": { "dompdf/dompdf": "^0.8", - "illuminate/support": "^5.5|^6", + "illuminate/support": "^5.5|^6|^7", "php": ">=7" }, "type": "library", @@ -144,25 +144,25 @@ "laravel", "pdf" ], - "time": "2019-08-23T14:30:33+00:00" + "time": "2020-02-25T20:44:34+00:00" }, { "name": "barryvdh/laravel-snappy", - "version": "v0.4.6", + "version": "v0.4.7", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-snappy.git", - "reference": "94d53c88fa58baa4573c5854663ebc9955f21265" + "reference": "c412d0c8f40b1326ba0fb16e94957fd1e68374f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-snappy/zipball/94d53c88fa58baa4573c5854663ebc9955f21265", - "reference": "94d53c88fa58baa4573c5854663ebc9955f21265", + "url": "https://api.github.com/repos/barryvdh/laravel-snappy/zipball/c412d0c8f40b1326ba0fb16e94957fd1e68374f0", + "reference": "c412d0c8f40b1326ba0fb16e94957fd1e68374f0", "shasum": "" }, "require": { - "illuminate/filesystem": "5.5.x|5.6.x|5.7.x|5.8.x|6.*", - "illuminate/support": "5.5.x|5.6.x|5.7.x|5.8.x|6.*", + "illuminate/filesystem": "^5.5|^6|^7", + "illuminate/support": "^5.5|^6|^7", "knplabs/knp-snappy": "^1", "php": ">=7" }, @@ -205,7 +205,7 @@ "wkhtmltoimage", "wkhtmltopdf" ], - "time": "2019-10-02T23:27:09+00:00" + "time": "2020-02-25T20:52:15+00:00" }, { "name": "cogpowered/finediff", @@ -639,16 +639,16 @@ }, { "name": "dompdf/dompdf", - "version": "v0.8.4", + "version": "v0.8.5", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "8f49b3b01693f51037dd50da81090beba1b5c005" + "reference": "6782abfc090b132134cd6cea0ec6d76f0fce2c56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/8f49b3b01693f51037dd50da81090beba1b5c005", - "reference": "8f49b3b01693f51037dd50da81090beba1b5c005", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/6782abfc090b132134cd6cea0ec6d76f0fce2c56", + "reference": "6782abfc090b132134cd6cea0ec6d76f0fce2c56", "shasum": "" }, "require": { @@ -701,7 +701,7 @@ ], "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", "homepage": "https://github.com/dompdf/dompdf", - "time": "2020-01-20T17:00:46+00:00" + "time": "2020-02-20T03:52:51+00:00" }, { "name": "dragonmantank/cron-expression", @@ -759,16 +759,16 @@ }, { "name": "egulias/email-validator", - "version": "2.1.15", + "version": "2.1.17", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "e834eea5306d85d67de5a05db5882911d5b29357" + "reference": "ade6887fd9bd74177769645ab5c474824f8a418a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/e834eea5306d85d67de5a05db5882911d5b29357", - "reference": "e834eea5306d85d67de5a05db5882911d5b29357", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ade6887fd9bd74177769645ab5c474824f8a418a", + "reference": "ade6887fd9bd74177769645ab5c474824f8a418a", "shasum": "" }, "require": { @@ -813,27 +813,27 @@ "validation", "validator" ], - "time": "2020-01-20T21:40:59+00:00" + "time": "2020-02-13T22:36:52+00:00" }, { "name": "facade/flare-client-php", - "version": "1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/facade/flare-client-php.git", - "reference": "24444ea0e1556f0a4b5fc8e61802caf72ae9a408" + "reference": "db1e03426e7f9472c9ecd1092aff00f56aa6c004" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/flare-client-php/zipball/24444ea0e1556f0a4b5fc8e61802caf72ae9a408", - "reference": "24444ea0e1556f0a4b5fc8e61802caf72ae9a408", + "url": "https://api.github.com/repos/facade/flare-client-php/zipball/db1e03426e7f9472c9ecd1092aff00f56aa6c004", + "reference": "db1e03426e7f9472c9ecd1092aff00f56aa6c004", "shasum": "" }, "require": { "facade/ignition-contracts": "~1.0", - "illuminate/pipeline": "~5.5|~5.6|~5.7|~5.8|^6.0", + "illuminate/pipeline": "^5.5|^6.0|^7.0", "php": "^7.1", - "symfony/http-foundation": "~3.3|~4.1", + "symfony/http-foundation": "^3.3|^4.1|^5.0", "symfony/var-dumper": "^3.4|^4.0|^5.0" }, "require-dev": { @@ -867,20 +867,20 @@ "flare", "reporting" ], - "time": "2019-12-15T18:28:38+00:00" + "time": "2020-03-02T15:52:04+00:00" }, { "name": "facade/ignition", - "version": "1.16.0", + "version": "1.16.1", "source": { "type": "git", "url": "https://github.com/facade/ignition.git", - "reference": "37f094775814b68d0c6cc8b8ff3c3be243f20725" + "reference": "af05ac5ee8587395d7474ec0681c08776a2cb09d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/ignition/zipball/37f094775814b68d0c6cc8b8ff3c3be243f20725", - "reference": "37f094775814b68d0c6cc8b8ff3c3be243f20725", + "url": "https://api.github.com/repos/facade/ignition/zipball/af05ac5ee8587395d7474ec0681c08776a2cb09d", + "reference": "af05ac5ee8587395d7474ec0681c08776a2cb09d", "shasum": "" }, "require": { @@ -907,7 +907,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "v2.x-dev" + "dev-master": "1.x-dev" }, "laravel": { "providers": [ @@ -938,7 +938,7 @@ "laravel", "page" ], - "time": "2020-01-21T17:46:02+00:00" + "time": "2020-03-05T12:39:07+00:00" }, { "name": "facade/ignition-contracts", @@ -986,24 +986,24 @@ }, { "name": "fideloper/proxy", - "version": "4.2.2", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/fideloper/TrustedProxy.git", - "reference": "790194d5d3da89a713478875d2e2d05855a90a81" + "reference": "ec38ad69ee378a1eec04fb0e417a97cfaf7ed11a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fideloper/TrustedProxy/zipball/790194d5d3da89a713478875d2e2d05855a90a81", - "reference": "790194d5d3da89a713478875d2e2d05855a90a81", + "url": "https://api.github.com/repos/fideloper/TrustedProxy/zipball/ec38ad69ee378a1eec04fb0e417a97cfaf7ed11a", + "reference": "ec38ad69ee378a1eec04fb0e417a97cfaf7ed11a", "shasum": "" }, "require": { - "illuminate/contracts": "^5.0|^6.0|^7.0", + "illuminate/contracts": "^5.0|^6.0|^7.0|^8.0", "php": ">=5.4.0" }, "require-dev": { - "illuminate/http": "^5.0|^6.0|^7.0", + "illuminate/http": "^5.0|^6.0|^7.0|^8.0", "mockery/mockery": "^1.0", "phpunit/phpunit": "^6.0" }, @@ -1036,7 +1036,7 @@ "proxy", "trusted proxy" ], - "time": "2019-12-20T13:11:11+00:00" + "time": "2020-02-22T01:51:47+00:00" }, { "name": "filp/whoops", @@ -1447,6 +1447,7 @@ "email": "jakub.onderka@gmail.com" } ], + "abandoned": "php-parallel-lint/php-console-color", "time": "2018-09-29T17:23:10+00:00" }, { @@ -1493,6 +1494,7 @@ } ], "description": "Highlight PHP code in terminal", + "abandoned": "php-parallel-lint/php-console-highlighter", "time": "2018-09-29T18:48:56+00:00" }, { @@ -1563,16 +1565,16 @@ }, { "name": "laravel/framework", - "version": "v6.12.0", + "version": "v6.18.3", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "8e189a8dee7ff76bf50acb7e80aa1a36afaf54d4" + "reference": "4e48acfaba87f08320a2764d36c3b6a4a4112ccf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/8e189a8dee7ff76bf50acb7e80aa1a36afaf54d4", - "reference": "8e189a8dee7ff76bf50acb7e80aa1a36afaf54d4", + "url": "https://api.github.com/repos/laravel/framework/zipball/4e48acfaba87f08320a2764d36c3b6a4a4112ccf", + "reference": "4e48acfaba87f08320a2764d36c3b6a4a4112ccf", "shasum": "" }, "require": { @@ -1582,8 +1584,7 @@ "ext-json": "*", "ext-mbstring": "*", "ext-openssl": "*", - "league/commonmark": "^1.1", - "league/commonmark-ext-table": "^2.1", + "league/commonmark": "^1.3", "league/flysystem": "^1.0.8", "monolog/monolog": "^1.12|^2.0", "nesbot/carbon": "^2.0", @@ -1641,7 +1642,7 @@ "aws/aws-sdk-php": "^3.0", "doctrine/dbal": "^2.6", "filp/whoops": "^2.4", - "guzzlehttp/guzzle": "^6.3", + "guzzlehttp/guzzle": "^6.3|^7.0", "league/flysystem-cached-adapter": "^1.0", "mockery/mockery": "^1.3.1", "moontoast/math": "^1.1", @@ -1658,11 +1659,11 @@ "ext-memcached": "Required to use the memcache cache driver.", "ext-pcntl": "Required to use all features of the queue worker.", "ext-posix": "Required to use all features of the queue worker.", - "ext-redis": "Required to use the Redis cache and queue drivers.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", "filp/whoops": "Required for friendly error pages in development (^2.4).", - "fzaninotto/faker": "Required to use the eloquent factory builder (^1.4).", - "guzzlehttp/guzzle": "Required to use the Mailgun mail driver and the ping methods on schedules (^6.0).", - "laravel/tinker": "Required to use the tinker console command (^1.0).", + "fzaninotto/faker": "Required to use the eloquent factory builder (^1.9.1).", + "guzzlehttp/guzzle": "Required to use the Mailgun mail driver and the ping methods on schedules (^6.0|^7.0).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", @@ -1706,20 +1707,20 @@ "framework", "laravel" ], - "time": "2020-01-21T15:10:03+00:00" + "time": "2020-03-24T16:37:50+00:00" }, { "name": "laravel/socialite", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "2d670d5b100ef2dc72dc578126b2b97985791f52" + "reference": "4bd66ee416fea04398dee5b8c32d65719a075db4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/2d670d5b100ef2dc72dc578126b2b97985791f52", - "reference": "2d670d5b100ef2dc72dc578126b2b97985791f52", + "url": "https://api.github.com/repos/laravel/socialite/zipball/4bd66ee416fea04398dee5b8c32d65719a075db4", + "reference": "4bd66ee416fea04398dee5b8c32d65719a075db4", "shasum": "" }, "require": { @@ -1738,7 +1739,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.x-dev" }, "laravel": { "providers": [ @@ -1770,34 +1771,35 @@ "laravel", "oauth" ], - "time": "2019-11-26T17:39:15+00:00" + "time": "2020-02-04T15:30:01+00:00" }, { "name": "league/commonmark", - "version": "1.2.2", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "34cf4ddb3892c715ae785c880e6691d839cff88d" + "reference": "75542a366ccbe1896ed79fcf3e8e68206d6c4257" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/34cf4ddb3892c715ae785c880e6691d839cff88d", - "reference": "34cf4ddb3892c715ae785c880e6691d839cff88d", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/75542a366ccbe1896ed79fcf3e8e68206d6c4257", + "reference": "75542a366ccbe1896ed79fcf3e8e68206d6c4257", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^7.1" }, - "replace": { - "colinodell/commonmark-php": "*" + "conflict": { + "scrutinizer/ocular": "1.7.*" }, "require-dev": { "cebe/markdown": "~1.0", "commonmark/commonmark.js": "0.29.1", "erusev/parsedown": "~1.0", "ext-json": "*", + "github/gfm": "0.29.0", "michelf/php-markdown": "~1.4", "mikehaertl/php-shellcommand": "^1.4", "phpstan/phpstan-shim": "^0.11.5", @@ -1805,16 +1807,13 @@ "scrutinizer/ocular": "^1.5", "symfony/finder": "^4.2" }, - "suggest": { - "league/commonmark-extras": "Library of useful extensions including smart punctuation" - }, "bin": [ "bin/commonmark" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -1834,92 +1833,32 @@ "role": "Lead Developer" } ], - "description": "PHP Markdown parser based on the CommonMark spec", + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and Github-Flavored Markdown (GFM)", "homepage": "https://commonmark.thephpleague.com", "keywords": [ "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", "markdown", + "md", "parser" ], - "time": "2020-01-16T01:18:13+00:00" - }, - { - "name": "league/commonmark-ext-table", - "version": "v2.1.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/commonmark-ext-table.git", - "reference": "3228888ea69636e855efcf6636ff8e6316933fe7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark-ext-table/zipball/3228888ea69636e855efcf6636ff8e6316933fe7", - "reference": "3228888ea69636e855efcf6636ff8e6316933fe7", - "shasum": "" - }, - "require": { - "league/commonmark": "~0.19.3|^1.0", - "php": "^7.1" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.14", - "phpstan/phpstan": "~0.11", - "phpunit/phpunit": "^7.0|^8.0", - "symfony/var-dumper": "^4.0", - "vimeo/psalm": "^3.0" - }, - "type": "commonmark-extension", - "extra": { - "branch-alias": { - "dev-master": "2.2-dev" - } - }, - "autoload": { - "psr-4": { - "League\\CommonMark\\Ext\\Table\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Martin Hasoň", - "email": "martin.hason@gmail.com" - }, - { - "name": "Webuni s.r.o.", - "homepage": "https://www.webuni.cz" - }, - { - "name": "Colin O'Dell", - "email": "colinodell@gmail.com", - "homepage": "https://www.colinodell.com" - } - ], - "description": "Table extension for league/commonmark", - "homepage": "https://github.com/thephpleague/commonmark-ext-table", - "keywords": [ - "commonmark", - "extension", - "markdown", - "table" - ], - "time": "2019-09-26T13:28:33+00:00" + "time": "2020-03-25T19:55:28+00:00" }, { "name": "league/flysystem", - "version": "1.0.63", + "version": "1.0.66", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "8132daec326565036bc8e8d1876f77ec183a7bd6" + "reference": "021569195e15f8209b1c4bebb78bd66aa4f08c21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/8132daec326565036bc8e8d1876f77ec183a7bd6", - "reference": "8132daec326565036bc8e8d1876f77ec183a7bd6", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/021569195e15f8209b1c4bebb78bd66aa4f08c21", + "reference": "021569195e15f8209b1c4bebb78bd66aa4f08c21", "shasum": "" }, "require": { @@ -1931,7 +1870,7 @@ }, "require-dev": { "phpspec/phpspec": "^3.4", - "phpunit/phpunit": "^5.7.10" + "phpunit/phpunit": "^5.7.26" }, "suggest": { "ext-fileinfo": "Required for MimeType", @@ -1990,20 +1929,20 @@ "sftp", "storage" ], - "time": "2020-01-04T16:30:31+00:00" + "time": "2020-03-17T18:58:12+00:00" }, { "name": "league/flysystem-aws-s3-v3", - "version": "1.0.23", + "version": "1.0.24", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "15b0cdeab7240bf8e8bffa85ae5275bbc3692bf4" + "reference": "4382036bde5dc926f9b8b337e5bdb15e5ec7b570" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/15b0cdeab7240bf8e8bffa85ae5275bbc3692bf4", - "reference": "15b0cdeab7240bf8e8bffa85ae5275bbc3692bf4", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/4382036bde5dc926f9b8b337e5bdb15e5ec7b570", + "reference": "4382036bde5dc926f9b8b337e5bdb15e5ec7b570", "shasum": "" }, "require": { @@ -2037,7 +1976,7 @@ } ], "description": "Flysystem adapter for the AWS S3 SDK v3.x", - "time": "2019-06-05T17:18:29+00:00" + "time": "2020-02-23T13:31:58+00:00" }, { "name": "league/oauth1-client", @@ -2242,16 +2181,16 @@ }, { "name": "nesbot/carbon", - "version": "2.29.1", + "version": "2.32.2", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "e509be5bf2d703390e69e14496d9a1168452b0a2" + "reference": "f10e22cf546704fab1db4ad4b9dedbc5c797a0dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/e509be5bf2d703390e69e14496d9a1168452b0a2", - "reference": "e509be5bf2d703390e69e14496d9a1168452b0a2", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f10e22cf546704fab1db4ad4b9dedbc5c797a0dc", + "reference": "f10e22cf546704fab1db4ad4b9dedbc5c797a0dc", "shasum": "" }, "require": { @@ -2260,6 +2199,7 @@ "symfony/translation": "^3.4 || ^4.0 || ^5.0" }, "require-dev": { + "doctrine/orm": "^2.7", "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", "kylekatarnls/multi-tester": "^1.1", "phpmd/phpmd": "^2.8", @@ -2308,7 +2248,7 @@ "datetime", "time" ], - "time": "2020-01-21T09:36:43+00:00" + "time": "2020-03-31T13:43:19+00:00" }, { "name": "nunomaduro/collision", @@ -2609,20 +2549,20 @@ }, { "name": "phpoption/phpoption", - "version": "1.7.2", + "version": "1.7.3", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "77f7c4d2e65413aff5b5a8cc8b3caf7a28d81959" + "reference": "4acfd6a4b33a509d8c88f50e5222f734b6aeebae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/77f7c4d2e65413aff5b5a8cc8b3caf7a28d81959", - "reference": "77f7c4d2e65413aff5b5a8cc8b3caf7a28d81959", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/4acfd6a4b33a509d8c88f50e5222f734b6aeebae", + "reference": "4acfd6a4b33a509d8c88f50e5222f734b6aeebae", "shasum": "" }, "require": { - "php": "^5.5.9 || ^7.0" + "php": "^5.5.9 || ^7.0 || ^8.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.3", @@ -2660,7 +2600,7 @@ "php", "type" ], - "time": "2019-12-15T19:35:24+00:00" + "time": "2020-03-21T18:07:53+00:00" }, { "name": "predis/predis", @@ -2813,16 +2753,16 @@ }, { "name": "psr/log", - "version": "1.1.2", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", + "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", "shasum": "" }, "require": { @@ -2856,7 +2796,7 @@ "psr", "psr-3" ], - "time": "2019-11-01T11:05:21+00:00" + "time": "2020-03-23T09:12:05+00:00" }, { "name": "psr/simple-cache", @@ -2948,16 +2888,16 @@ }, { "name": "ramsey/uuid", - "version": "3.9.2", + "version": "3.9.3", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "7779489a47d443f845271badbdcedfe4df8e06fb" + "reference": "7e1633a6964b48589b142d60542f9ed31bd37a92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/7779489a47d443f845271badbdcedfe4df8e06fb", - "reference": "7779489a47d443f845271badbdcedfe4df8e06fb", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/7e1633a6964b48589b142d60542f9ed31bd37a92", + "reference": "7e1633a6964b48589b142d60542f9ed31bd37a92", "shasum": "" }, "require": { @@ -3031,7 +2971,7 @@ "identifier", "uuid" ], - "time": "2019-12-17T08:18:51+00:00" + "time": "2020-02-21T04:36:14+00:00" }, { "name": "robrichards/xmlseclibs", @@ -3118,16 +3058,16 @@ }, { "name": "scrivo/highlight.php", - "version": "v9.17.1.0", + "version": "v9.18.1.1", "source": { "type": "git", "url": "https://github.com/scrivo/highlight.php.git", - "reference": "5451a9ad6d638559cf2a092880f935c39776134e" + "reference": "52fc21c99fd888e33aed4879e55a3646f8d40558" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/5451a9ad6d638559cf2a092880f935c39776134e", - "reference": "5451a9ad6d638559cf2a092880f935c39776134e", + "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/52fc21c99fd888e33aed4879e55a3646f8d40558", + "reference": "52fc21c99fd888e33aed4879e55a3646f8d40558", "shasum": "" }, "require": { @@ -3137,8 +3077,9 @@ }, "require-dev": { "phpunit/phpunit": "^4.8|^5.7", - "symfony/finder": "^3.4", - "symfony/var-dumper": "^3.4" + "sabberworm/php-css-parser": "^8.3", + "symfony/finder": "^2.8|^3.4", + "symfony/var-dumper": "^2.8|^3.4" }, "suggest": { "ext-dom": "Needed to make use of the features in the utilities namespace" @@ -3182,7 +3123,7 @@ "highlight.php", "syntax" ], - "time": "2019-12-13T21:54:06+00:00" + "time": "2020-03-02T05:59:21+00:00" }, { "name": "socialiteproviders/discord", @@ -3260,20 +3201,20 @@ }, { "name": "socialiteproviders/manager", - "version": "v3.4.3", + "version": "v3.5", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Manager.git", - "reference": "09903d33429f9f6c0da32c545c036a3e18964bbf" + "reference": "7a5872d9e4b22bb26ecd0c69ea9ddbaad8c0f570" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/09903d33429f9f6c0da32c545c036a3e18964bbf", - "reference": "09903d33429f9f6c0da32c545c036a3e18964bbf", + "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/7a5872d9e4b22bb26ecd0c69ea9ddbaad8c0f570", + "reference": "7a5872d9e4b22bb26ecd0c69ea9ddbaad8c0f570", "shasum": "" }, "require": { - "illuminate/support": "~5.4|~5.7.0|~5.8.0|^6.0", + "illuminate/support": "~5.4|~5.7.0|~5.8.0|^6.0|^7.0", "laravel/socialite": "~3.0|~4.0", "php": "^5.6 || ^7.0" }, @@ -3313,7 +3254,7 @@ } ], "description": "Easily add new or override built-in providers in Laravel Socialite.", - "time": "2019-09-25T06:06:35+00:00" + "time": "2020-03-08T16:54:44+00:00" }, { "name": "socialiteproviders/microsoft-azure", @@ -3527,16 +3468,16 @@ }, { "name": "symfony/console", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "e9ee09d087e2c88eaf6e5fc0f5c574f64d100e4f" + "reference": "10bb3ee3c97308869d53b3e3d03f6ac23ff985f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e9ee09d087e2c88eaf6e5fc0f5c574f64d100e4f", - "reference": "e9ee09d087e2c88eaf6e5fc0f5c574f64d100e4f", + "url": "https://api.github.com/repos/symfony/console/zipball/10bb3ee3c97308869d53b3e3d03f6ac23ff985f7", + "reference": "10bb3ee3c97308869d53b3e3d03f6ac23ff985f7", "shasum": "" }, "require": { @@ -3599,20 +3540,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2020-01-10T21:54:01+00:00" + "time": "2020-03-30T11:41:10+00:00" }, { "name": "symfony/css-selector", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "a167b1860995b926d279f9bb538f873e3bfa3465" + "reference": "afc26133a6fbdd4f8842e38893e0ee4685c7c94b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/a167b1860995b926d279f9bb538f873e3bfa3465", - "reference": "a167b1860995b926d279f9bb538f873e3bfa3465", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/afc26133a6fbdd4f8842e38893e0ee4685c7c94b", + "reference": "afc26133a6fbdd4f8842e38893e0ee4685c7c94b", "shasum": "" }, "require": { @@ -3652,20 +3593,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/debug", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "89c3fd5c299b940333bc6fe9f1b8db1b0912c759" + "reference": "346636d2cae417992ecfd761979b2ab98b339a45" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/89c3fd5c299b940333bc6fe9f1b8db1b0912c759", - "reference": "89c3fd5c299b940333bc6fe9f1b8db1b0912c759", + "url": "https://api.github.com/repos/symfony/debug/zipball/346636d2cae417992ecfd761979b2ab98b339a45", + "reference": "346636d2cae417992ecfd761979b2ab98b339a45", "shasum": "" }, "require": { @@ -3708,26 +3649,26 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2020-01-08T17:29:02+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/error-handler", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "a59789092e40ad08465dc2cdc55651be503d0d5a" + "reference": "7e9828fc98aa1cf27b422fe478a84f5b0abb7358" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/a59789092e40ad08465dc2cdc55651be503d0d5a", - "reference": "a59789092e40ad08465dc2cdc55651be503d0d5a", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/7e9828fc98aa1cf27b422fe478a84f5b0abb7358", + "reference": "7e9828fc98aa1cf27b422fe478a84f5b0abb7358", "shasum": "" }, "require": { "php": "^7.1.3", "psr/log": "~1.0", - "symfony/debug": "^4.4", + "symfony/debug": "^4.4.5", "symfony/var-dumper": "^4.4|^5.0" }, "require-dev": { @@ -3764,20 +3705,20 @@ ], "description": "Symfony ErrorHandler Component", "homepage": "https://symfony.com", - "time": "2020-01-08T17:29:02+00:00" + "time": "2020-03-30T14:07:33+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9e3de195e5bc301704dd6915df55892f6dfc208b" + "reference": "abc8e3618bfdb55e44c8c6a00abd333f831bbfed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9e3de195e5bc301704dd6915df55892f6dfc208b", - "reference": "9e3de195e5bc301704dd6915df55892f6dfc208b", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/abc8e3618bfdb55e44c8c6a00abd333f831bbfed", + "reference": "abc8e3618bfdb55e44c8c6a00abd333f831bbfed", "shasum": "" }, "require": { @@ -3834,7 +3775,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2020-01-10T21:54:01+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -3896,16 +3837,16 @@ }, { "name": "symfony/finder", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "3a50be43515590faf812fbd7708200aabc327ec3" + "reference": "5729f943f9854c5781984ed4907bbb817735776b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/3a50be43515590faf812fbd7708200aabc327ec3", - "reference": "3a50be43515590faf812fbd7708200aabc327ec3", + "url": "https://api.github.com/repos/symfony/finder/zipball/5729f943f9854c5781984ed4907bbb817735776b", + "reference": "5729f943f9854c5781984ed4907bbb817735776b", "shasum": "" }, "require": { @@ -3941,20 +3882,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/http-foundation", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "c33998709f3fe9b8e27e0277535b07fbf6fde37a" + "reference": "62f92509c9abfd1f73e17b8cf1b72c0bdac6611b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/c33998709f3fe9b8e27e0277535b07fbf6fde37a", - "reference": "c33998709f3fe9b8e27e0277535b07fbf6fde37a", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/62f92509c9abfd1f73e17b8cf1b72c0bdac6611b", + "reference": "62f92509c9abfd1f73e17b8cf1b72c0bdac6611b", "shasum": "" }, "require": { @@ -3996,20 +3937,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-30T14:07:33+00:00" }, { "name": "symfony/http-kernel", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "16f2aa3c54b08483fba5375938f60b1ff83b6bd2" + "reference": "f356a489e51856b99908005eb7f2c51a1dfc95dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/16f2aa3c54b08483fba5375938f60b1ff83b6bd2", - "reference": "16f2aa3c54b08483fba5375938f60b1ff83b6bd2", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f356a489e51856b99908005eb7f2c51a1dfc95dc", + "reference": "f356a489e51856b99908005eb7f2c51a1dfc95dc", "shasum": "" }, "require": { @@ -4086,20 +4027,20 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2020-01-21T13:23:17+00:00" + "time": "2020-03-30T14:59:15+00:00" }, { "name": "symfony/mime", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "225034620ecd4b34fd826e9983d85e2b7a359094" + "reference": "6dde9dc70155e91b850b1d009d1f841c54bc4aba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/225034620ecd4b34fd826e9983d85e2b7a359094", - "reference": "225034620ecd4b34fd826e9983d85e2b7a359094", + "url": "https://api.github.com/repos/symfony/mime/zipball/6dde9dc70155e91b850b1d009d1f841c54bc4aba", + "reference": "6dde9dc70155e91b850b1d009d1f841c54bc4aba", "shasum": "" }, "require": { @@ -4148,20 +4089,20 @@ "mime", "mime-type" ], - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.13.1", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" + "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", - "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", + "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", "shasum": "" }, "require": { @@ -4173,7 +4114,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -4206,20 +4147,20 @@ "polyfill", "portable" ], - "time": "2019-11-27T13:56:44+00:00" + "time": "2020-02-27T09:26:54+00:00" }, { "name": "symfony/polyfill-iconv", - "version": "v1.13.1", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "a019efccc03f1a335af6b4f20c30f5ea8060be36" + "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/a019efccc03f1a335af6b4f20c30f5ea8060be36", - "reference": "a019efccc03f1a335af6b4f20c30f5ea8060be36", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/ad6d62792bfbcfc385dd34b424d4fcf9712a32c8", + "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8", "shasum": "" }, "require": { @@ -4231,7 +4172,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -4265,26 +4206,26 @@ "portable", "shim" ], - "time": "2019-11-27T13:56:44+00:00" + "time": "2020-03-09T19:04:49+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.13.1", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46" + "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6f9c239e61e1b0c9229a28ff89a812dc449c3d46", - "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", + "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", "shasum": "" }, "require": { "php": ">=5.3.3", "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php72": "^1.9" + "symfony/polyfill-php72": "^1.10" }, "suggest": { "ext-intl": "For best performance" @@ -4292,7 +4233,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -4327,20 +4268,20 @@ "portable", "shim" ], - "time": "2019-11-27T13:56:44+00:00" + "time": "2020-03-09T19:04:49+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.13.1", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" + "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", - "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", + "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", "shasum": "" }, "require": { @@ -4352,7 +4293,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -4386,20 +4327,20 @@ "portable", "shim" ], - "time": "2019-11-27T14:18:11+00:00" + "time": "2020-03-09T19:04:49+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.13.1", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038" + "reference": "37b0976c78b94856543260ce09b460a7bc852747" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/66fea50f6cb37a35eea048d75a7d99a45b586038", - "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747", + "reference": "37b0976c78b94856543260ce09b460a7bc852747", "shasum": "" }, "require": { @@ -4408,7 +4349,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -4441,20 +4382,20 @@ "portable", "shim" ], - "time": "2019-11-27T13:56:44+00:00" + "time": "2020-02-27T09:26:54+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.13.1", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f" + "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/4b0e2222c55a25b4541305a053013d5647d3a25f", - "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", + "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", "shasum": "" }, "require": { @@ -4463,7 +4404,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.15-dev" } }, "autoload": { @@ -4499,20 +4440,20 @@ "portable", "shim" ], - "time": "2019-11-27T16:25:15+00:00" + "time": "2020-02-27T09:26:54+00:00" }, { "name": "symfony/process", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "f5697ab4cb14a5deed7473819e63141bf5352c36" + "reference": "3e40e87a20eaf83a1db825e1fa5097ae89042db3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/f5697ab4cb14a5deed7473819e63141bf5352c36", - "reference": "f5697ab4cb14a5deed7473819e63141bf5352c36", + "url": "https://api.github.com/repos/symfony/process/zipball/3e40e87a20eaf83a1db825e1fa5097ae89042db3", + "reference": "3e40e87a20eaf83a1db825e1fa5097ae89042db3", "shasum": "" }, "require": { @@ -4548,20 +4489,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2020-01-09T09:50:08+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/routing", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "7bf4e38573728e317b926ca4482ad30470d0e86a" + "reference": "0f562fa613e288d7dbae6c63abbc9b33ed75a8f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/7bf4e38573728e317b926ca4482ad30470d0e86a", - "reference": "7bf4e38573728e317b926ca4482ad30470d0e86a", + "url": "https://api.github.com/repos/symfony/routing/zipball/0f562fa613e288d7dbae6c63abbc9b33ed75a8f8", + "reference": "0f562fa613e288d7dbae6c63abbc9b33ed75a8f8", "shasum": "" }, "require": { @@ -4624,7 +4565,7 @@ "uri", "url" ], - "time": "2020-01-08T17:29:02+00:00" + "time": "2020-03-30T11:41:10+00:00" }, { "name": "symfony/service-contracts", @@ -4686,16 +4627,16 @@ }, { "name": "symfony/translation", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "f5d2ac46930238b30a9c2f1b17c905f3697d808c" + "reference": "4e54d336f2eca5facad449d0b0118bb449375b76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/f5d2ac46930238b30a9c2f1b17c905f3697d808c", - "reference": "f5d2ac46930238b30a9c2f1b17c905f3697d808c", + "url": "https://api.github.com/repos/symfony/translation/zipball/4e54d336f2eca5facad449d0b0118bb449375b76", + "reference": "4e54d336f2eca5facad449d0b0118bb449375b76", "shasum": "" }, "require": { @@ -4758,7 +4699,7 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2020-01-15T13:29:06+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/translation-contracts", @@ -4819,16 +4760,16 @@ }, { "name": "symfony/var-dumper", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7cfa470bc3b1887a7b2a47c0a702a84ad614fa92" + "reference": "5a0c2d93006131a36cf6f767d10e2ca8333b0d4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7cfa470bc3b1887a7b2a47c0a702a84ad614fa92", - "reference": "7cfa470bc3b1887a7b2a47c0a702a84ad614fa92", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/5a0c2d93006131a36cf6f767d10e2ca8333b0d4a", + "reference": "5a0c2d93006131a36cf6f767d10e2ca8333b0d4a", "shasum": "" }, "require": { @@ -4891,7 +4832,7 @@ "debug", "dump" ], - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -4944,16 +4885,16 @@ }, { "name": "vlucas/phpdotenv", - "version": "v3.6.0", + "version": "v3.6.2", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "1bdf24f065975594f6a117f0f1f6cabf1333b156" + "reference": "786a947e57086cf236cefdee80784634224b99fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1bdf24f065975594f6a117f0f1f6cabf1333b156", - "reference": "1bdf24f065975594f6a117f0f1f6cabf1333b156", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/786a947e57086cf236cefdee80784634224b99fa", + "reference": "786a947e57086cf236cefdee80784634224b99fa", "shasum": "" }, "require": { @@ -4962,8 +4903,14 @@ "symfony/polyfill-ctype": "^1.9" }, "require-dev": { + "ext-filter": "*", + "ext-pcre": "*", "phpunit/phpunit": "^4.8.35 || ^5.0 || ^6.0 || ^7.0" }, + "suggest": { + "ext-filter": "Required to use the boolean validator.", + "ext-pcre": "Required to use most of the library." + }, "type": "library", "extra": { "branch-alias": { @@ -4997,32 +4944,32 @@ "env", "environment" ], - "time": "2019-09-10T21:37:39+00:00" + "time": "2020-03-27T23:36:02+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.2.8", + "version": "v3.2.9", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "18208d64897ab732f6c04a19b319fe8f1d57a9c0" + "reference": "42d5da5379a7860093f8e4032167e4cb5ebec180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/18208d64897ab732f6c04a19b319fe8f1d57a9c0", - "reference": "18208d64897ab732f6c04a19b319fe8f1d57a9c0", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/42d5da5379a7860093f8e4032167e4cb5ebec180", + "reference": "42d5da5379a7860093f8e4032167e4cb5ebec180", "shasum": "" }, "require": { - "illuminate/routing": "^5.5|^6", - "illuminate/session": "^5.5|^6", - "illuminate/support": "^5.5|^6", - "maximebf/debugbar": "~1.15.0", + "illuminate/routing": "^5.5|^6|^7", + "illuminate/session": "^5.5|^6|^7", + "illuminate/support": "^5.5|^6|^7", + "maximebf/debugbar": "^1.15.1", "php": ">=7.0", - "symfony/debug": "^3|^4", - "symfony/finder": "^3|^4" + "symfony/debug": "^3|^4|^5", + "symfony/finder": "^3|^4|^5" }, "require-dev": { "laravel/framework": "5.5.x" @@ -5067,37 +5014,37 @@ "profiler", "webprofiler" ], - "time": "2019-08-29T07:01:03+00:00" + "time": "2020-02-25T20:42:23+00:00" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v2.6.6", + "version": "v2.6.7", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "b91b959364d97af658f268c733c75dccdbff197e" + "reference": "edd69c5e0508972c81f1f7173236de2459c45814" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/b91b959364d97af658f268c733c75dccdbff197e", - "reference": "b91b959364d97af658f268c733c75dccdbff197e", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/edd69c5e0508972c81f1f7173236de2459c45814", + "reference": "edd69c5e0508972c81f1f7173236de2459c45814", "shasum": "" }, "require": { "barryvdh/reflection-docblock": "^2.0.6", "composer/composer": "^1.6", "doctrine/dbal": "~2.3", - "illuminate/console": "^5.5|^6", - "illuminate/filesystem": "^5.5|^6", - "illuminate/support": "^5.5|^6", - "php": ">=7" + "illuminate/console": "^5.5|^6|^7", + "illuminate/filesystem": "^5.5|^6|^7", + "illuminate/support": "^5.5|^6|^7", + "php": ">=7.2" }, "require-dev": { - "illuminate/config": "^5.5|^6", - "illuminate/view": "^5.5|^6", - "phpro/grumphp": "^0.14", - "phpunit/phpunit": "4.*", - "scrutinizer/ocular": "~1.1", + "illuminate/config": "^5.5|^6|^7", + "illuminate/view": "^5.5|^6|^7", + "mockery/mockery": "^1.3", + "orchestra/testbench": "^3|^4", + "phpro/grumphp": "^0.17.1", "squizlabs/php_codesniffer": "^3" }, "type": "library", @@ -5138,7 +5085,7 @@ "phpstorm", "sublime" ], - "time": "2019-10-30T20:53:27+00:00" + "time": "2020-02-25T20:41:32+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -5247,16 +5194,16 @@ }, { "name": "composer/composer", - "version": "1.9.2", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "7a04aa0201ddaa0b3cf64d41022bd8cdcd7fafeb" + "reference": "b912a45da3e2b22f5cb5a23e441b697a295ba011" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/7a04aa0201ddaa0b3cf64d41022bd8cdcd7fafeb", - "reference": "7a04aa0201ddaa0b3cf64d41022bd8cdcd7fafeb", + "url": "https://api.github.com/repos/composer/composer/zipball/b912a45da3e2b22f5cb5a23e441b697a295ba011", + "reference": "b912a45da3e2b22f5cb5a23e441b697a295ba011", "shasum": "" }, "require": { @@ -5269,17 +5216,17 @@ "psr/log": "^1.0", "seld/jsonlint": "^1.4", "seld/phar-utils": "^1.0", - "symfony/console": "^2.7 || ^3.0 || ^4.0", - "symfony/filesystem": "^2.7 || ^3.0 || ^4.0", - "symfony/finder": "^2.7 || ^3.0 || ^4.0", - "symfony/process": "^2.7 || ^3.0 || ^4.0" + "symfony/console": "^2.7 || ^3.0 || ^4.0 || ^5.0", + "symfony/filesystem": "^2.7 || ^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^2.7 || ^3.0 || ^4.0 || ^5.0", + "symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0" }, "conflict": { "symfony/console": "2.8.38" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7", - "phpunit/phpunit-mock-objects": "^2.3 || ^3.0" + "phpspec/prophecy": "^1.10", + "symfony/phpunit-bridge": "^3.4" }, "suggest": { "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", @@ -5292,7 +5239,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.10-dev" } }, "autoload": { @@ -5323,7 +5270,7 @@ "dependency", "package" ], - "time": "2020-01-14T15:30:32+00:00" + "time": "2020-03-13T19:34:27+00:00" }, { "name": "composer/semver", @@ -5388,16 +5335,16 @@ }, { "name": "composer/spdx-licenses", - "version": "1.5.2", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/composer/spdx-licenses.git", - "reference": "7ac1e6aec371357df067f8a688c3d6974df68fa5" + "reference": "0c3e51e1880ca149682332770e25977c70cf9dae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/7ac1e6aec371357df067f8a688c3d6974df68fa5", - "reference": "7ac1e6aec371357df067f8a688c3d6974df68fa5", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/0c3e51e1880ca149682332770e25977c70cf9dae", + "reference": "0c3e51e1880ca149682332770e25977c70cf9dae", "shasum": "" }, "require": { @@ -5444,20 +5391,20 @@ "spdx", "validator" ], - "time": "2019-07-29T10:31:59+00:00" + "time": "2020-02-14T07:44:31+00:00" }, { "name": "composer/xdebug-handler", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "cbe23383749496fe0f373345208b79568e4bc248" + "reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/cbe23383749496fe0f373345208b79568e4bc248", - "reference": "cbe23383749496fe0f373345208b79568e4bc248", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/1ab9842d69e64fb3a01be6b656501032d1b78cb7", + "reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7", "shasum": "" }, "require": { @@ -5488,7 +5435,7 @@ "Xdebug", "performance" ], - "time": "2019-11-06T16:40:04+00:00" + "time": "2020-03-01T12:26:26+00:00" }, { "name": "doctrine/instantiator", @@ -5773,22 +5720,22 @@ }, { "name": "maximebf/debugbar", - "version": "v1.15.1", + "version": "v1.16.1", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "6c4277f6117e4864966c9cb58fb835cee8c74a1e" + "reference": "58998b818c6567fac01e35b8a4b70c1a64530556" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/6c4277f6117e4864966c9cb58fb835cee8c74a1e", - "reference": "6c4277f6117e4864966c9cb58fb835cee8c74a1e", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/58998b818c6567fac01e35b8a4b70c1a64530556", + "reference": "58998b818c6567fac01e35b8a4b70c1a64530556", "shasum": "" }, "require": { - "php": ">=5.6", + "php": "^7.1", "psr/log": "^1.0", - "symfony/var-dumper": "^2.6|^3|^4" + "symfony/var-dumper": "^2.6|^3|^4|^5" }, "require-dev": { "phpunit/phpunit": "^5" @@ -5801,7 +5748,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.16-dev" } }, "autoload": { @@ -5830,7 +5777,7 @@ "debug", "debugbar" ], - "time": "2019-09-24T14:55:42+00:00" + "time": "2019-11-24T09:46:11+00:00" }, { "name": "mockery/mockery", @@ -6101,41 +6048,38 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.4", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", - "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", - "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", - "webmozart/assert": "^1.0" + "ext-filter": "^7.1", + "php": "^7.2", + "phpdocumentor/reflection-common": "^2.0", + "phpdocumentor/type-resolver": "^1.0", + "webmozart/assert": "^1" }, "require-dev": { - "doctrine/instantiator": "^1.0.5", - "mockery/mockery": "^1.0", - "phpdocumentor/type-resolver": "0.4.*", - "phpunit/phpunit": "^6.4" + "doctrine/instantiator": "^1", + "mockery/mockery": "^1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -6146,33 +6090,36 @@ { "name": "Mike van Riel", "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-12-28T18:55:12+00:00" + "time": "2020-02-22T12:28:44+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.0.1", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" + "reference": "7462d5f123dfc080dfdf26897032a6513644fc95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95", + "reference": "7462d5f123dfc080dfdf26897032a6513644fc95", "shasum": "" }, "require": { - "php": "^7.1", + "php": "^7.2", "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "^7.1", - "mockery/mockery": "~1", - "phpunit/phpunit": "^7.0" + "ext-tokenizer": "^7.2", + "mockery/mockery": "~1" }, "type": "library", "extra": { @@ -6196,7 +6143,7 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2019-08-22T18:11:29+00:00" + "time": "2020-02-18T18:59:58+00:00" }, { "name": "phploc/phploc", @@ -6249,16 +6196,16 @@ }, { "name": "phpspec/prophecy", - "version": "v1.10.2", + "version": "v1.10.3", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9" + "reference": "451c3cd1418cf640de218914901e51b064abb093" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b4400efc9d206e83138e2bb97ed7f5b14b831cd9", - "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", "shasum": "" }, "require": { @@ -6308,7 +6255,7 @@ "spy", "stub" ], - "time": "2020-01-20T15:57:02+00:00" + "time": "2020-03-05T15:02:03+00:00" }, { "name": "phpunit/php-code-coverage", @@ -6564,16 +6511,16 @@ }, { "name": "phpunit/phpunit", - "version": "8.5.2", + "version": "8.5.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "018b6ac3c8ab20916db85fa91bf6465acb64d1e0" + "reference": "67750516bc02f300e2742fed2f50177f8f37bedf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/018b6ac3c8ab20916db85fa91bf6465acb64d1e0", - "reference": "018b6ac3c8ab20916db85fa91bf6465acb64d1e0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/67750516bc02f300e2742fed2f50177f8f37bedf", + "reference": "67750516bc02f300e2742fed2f50177f8f37bedf", "shasum": "" }, "require": { @@ -6643,7 +6590,7 @@ "testing", "xunit" ], - "time": "2020-01-08T08:49:49+00:00" + "time": "2020-03-31T08:52:04+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -7354,16 +7301,16 @@ }, { "name": "seld/phar-utils", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/Seldaek/phar-utils.git", - "reference": "84715761c35808076b00908a20317a3a8a67d17e" + "reference": "8800503d56b9867d43d9c303b9cbcc26016e82f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/84715761c35808076b00908a20317a3a8a67d17e", - "reference": "84715761c35808076b00908a20317a3a8a67d17e", + "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/8800503d56b9867d43d9c303b9cbcc26016e82f0", + "reference": "8800503d56b9867d43d9c303b9cbcc26016e82f0", "shasum": "" }, "require": { @@ -7392,22 +7339,22 @@ ], "description": "PHAR file format utilities, for when PHP phars you up", "keywords": [ - "phra" + "phar" ], - "time": "2020-01-13T10:41:09+00:00" + "time": "2020-02-14T15:25:33+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.5.3", + "version": "3.5.4", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "557a1fc7ac702c66b0bbfe16ab3d55839ef724cb" + "reference": "dceec07328401de6211037abbb18bda423677e26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/557a1fc7ac702c66b0bbfe16ab3d55839ef724cb", - "reference": "557a1fc7ac702c66b0bbfe16ab3d55839ef724cb", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dceec07328401de6211037abbb18bda423677e26", + "reference": "dceec07328401de6211037abbb18bda423677e26", "shasum": "" }, "require": { @@ -7445,20 +7392,20 @@ "phpcs", "standards" ], - "time": "2019-12-04T04:46:47+00:00" + "time": "2020-01-30T22:20:29+00:00" }, { "name": "symfony/dom-crawler", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "b66fe8ccc850ea11c4cd31677706c1219768bea1" + "reference": "4d0fb3374324071ecdd94898367a3fa4b5563162" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b66fe8ccc850ea11c4cd31677706c1219768bea1", - "reference": "b66fe8ccc850ea11c4cd31677706c1219768bea1", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/4d0fb3374324071ecdd94898367a3fa4b5563162", + "reference": "4d0fb3374324071ecdd94898367a3fa4b5563162", "shasum": "" }, "require": { @@ -7506,20 +7453,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2020-01-04T13:00:46+00:00" + "time": "2020-03-29T19:12:22+00:00" }, { "name": "symfony/filesystem", - "version": "v4.4.3", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "266c9540b475f26122b61ef8b23dd9198f5d1cfd" + "reference": "fe297193bf2e6866ed900ed2d5869362768df6a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/266c9540b475f26122b61ef8b23dd9198f5d1cfd", - "reference": "266c9540b475f26122b61ef8b23dd9198f5d1cfd", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/fe297193bf2e6866ed900ed2d5869362768df6a7", + "reference": "fe297193bf2e6866ed900ed2d5869362768df6a7", "shasum": "" }, "require": { @@ -7556,7 +7503,7 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2020-01-21T08:20:44+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "theseer/fdomdocument", @@ -7640,16 +7587,16 @@ }, { "name": "webmozart/assert", - "version": "1.6.0", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "573381c0a64f155a0d9a23f4b0c797194805b925" + "reference": "aed98a490f9a8f78468232db345ab9cf606cf598" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925", - "reference": "573381c0a64f155a0d9a23f4b0c797194805b925", + "url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598", + "reference": "aed98a490f9a8f78468232db345ab9cf606cf598", "shasum": "" }, "require": { @@ -7684,35 +7631,36 @@ "check", "validate" ], - "time": "2019-11-24T13:36:37+00:00" + "time": "2020-02-14T12:15:55+00:00" }, { "name": "wnx/laravel-stats", - "version": "v2.0.0", + "version": "v2.0.2", "source": { "type": "git", "url": "https://github.com/stefanzweifel/laravel-stats.git", - "reference": "1b3c60bfbf81233973cbc2a63be4e6f83b2d6205" + "reference": "e86ebfdd149383b18a41fe3efa1601d82d447140" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stefanzweifel/laravel-stats/zipball/1b3c60bfbf81233973cbc2a63be4e6f83b2d6205", - "reference": "1b3c60bfbf81233973cbc2a63be4e6f83b2d6205", + "url": "https://api.github.com/repos/stefanzweifel/laravel-stats/zipball/e86ebfdd149383b18a41fe3efa1601d82d447140", + "reference": "e86ebfdd149383b18a41fe3efa1601d82d447140", "shasum": "" }, "require": { - "illuminate/console": "~5.8.0|^6.0", - "illuminate/support": "~5.8.0|^6.0", + "illuminate/console": "~5.8.0|^6.0|^7.0", + "illuminate/support": "~5.8.0|^6.0|^7.0", "php": ">=7.2.0", - "phploc/phploc": "~4.0|~5.0", - "symfony/finder": "~3.3|~4.0" + "phploc/phploc": "~5.0|~6.0", + "symfony/finder": "~4.0" }, "require-dev": { - "laravel/browser-kit-testing": "~2.0|~3.0|~4.0|~5.0", - "laravel/dusk": "~3.0|~4.0|~5.0", + "friendsofphp/php-cs-fixer": "^2.15", + "laravel/browser-kit-testing": "~5.0", + "laravel/dusk": "~5.0", "mockery/mockery": "^1.1", - "orchestra/testbench": "^3.8", - "phpunit/phpunit": "6.*|7.*|8.*" + "orchestra/testbench": "^3.8|^4.0|^5.0", + "phpunit/phpunit": "8.*|9.*" }, "type": "library", "extra": { @@ -7747,7 +7695,7 @@ "stats", "wnx" ], - "time": "2019-09-01T14:18:49+00:00" + "time": "2020-02-22T19:09:14+00:00" } ], "aliases": [], From c1fe068ffc148d73747484e77e8e0a0983bda898 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 4 Apr 2020 00:03:26 +0100 Subject: [PATCH 007/197] Bumped npm packages up and ran audit-fix --- package-lock.json | 333 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 165 insertions(+), 172 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a2676c7d..243a19a9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3,178 +3,177 @@ "lockfileVersion": 1, "dependencies": { "@webassemblyjs/ast": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", - "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", "dev": true, "requires": { - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5" + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", - "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", - "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", - "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", "dev": true }, "@webassemblyjs/helper-code-frame": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", - "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", "dev": true, "requires": { - "@webassemblyjs/wast-printer": "1.8.5" + "@webassemblyjs/wast-printer": "1.9.0" } }, "@webassemblyjs/helper-fsm": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", - "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", "dev": true }, "@webassemblyjs/helper-module-context": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", - "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "mamacro": "^0.0.3" + "@webassemblyjs/ast": "1.9.0" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", - "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", - "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" } }, "@webassemblyjs/ieee754": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", - "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", - "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", "dev": true, "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", - "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", - "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/helper-wasm-section": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-opt": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "@webassemblyjs/wast-printer": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" } }, "@webassemblyjs/wasm-gen": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", - "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" } }, "@webassemblyjs/wasm-opt": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", - "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" } }, "@webassemblyjs/wasm-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", - "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" } }, "@webassemblyjs/wast-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", - "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/floating-point-hex-parser": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-code-frame": "1.8.5", - "@webassemblyjs/helper-fsm": "1.8.5", + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/wast-printer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", - "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5", + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", "@xtuc/long": "4.2.2" } }, @@ -367,7 +366,7 @@ }, "util": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -566,7 +565,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -603,7 +602,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { @@ -671,9 +670,9 @@ "dev": true }, "cacache": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", - "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", "dev": true, "requires": { "bluebird": "^3.5.5", @@ -883,9 +882,9 @@ "dev": true }, "codemirror": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.52.0.tgz", - "integrity": "sha512-K2UB6zjscrfME03HeRe/IuOmCeqNpw7PLKGHThYpLbZEuKf+ZoujJPhxZN4hHJS1O7QyzEsV7JJZGxuQWVaFCg==" + "version": "5.52.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.52.2.tgz", + "integrity": "sha512-WCGCixNUck2HGvY8/ZNI1jYfxPG5cRHv0VjmWuNzbtCLz8qYA5d+je4QhSSCtCaagyeOwMi/HmmPTjBgiTm2lQ==" }, "collection-visit": { "version": "1.0.0", @@ -1013,7 +1012,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -1026,7 +1025,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -1223,7 +1222,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { @@ -1603,9 +1602,9 @@ "dev": true }, "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", "dev": true }, "fill-range": { @@ -2503,7 +2502,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -2588,12 +2587,6 @@ } } }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", - "dev": true - }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -2885,9 +2878,9 @@ } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "mississippi": { @@ -2930,20 +2923,12 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } + "minimist": "^1.2.5" } }, "move-concurrently": { @@ -3103,7 +3088,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -3527,7 +3512,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -4073,7 +4058,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -4224,7 +4209,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -4690,9 +4675,9 @@ } }, "terser": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.6.tgz", - "integrity": "sha512-4lYPyeNmstjIIESr/ysHg2vUPRGf2tzF9z2yYwnowXVuVzLEamPN1Gfrz7f8I9uEPuHcbFlW4PLIAsJoxXyJ1g==", + "version": "4.6.10", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.10.tgz", + "integrity": "sha512-qbF/3UOo11Hggsbsqm2hPa6+L4w7bkr+09FNseEe8xrcVD3APGLFqE+Oz1ZKAxjYnFsj80rLOfgAtJ0LNJjtTA==", "dev": true, "requires": { "commander": "^2.20.0", @@ -5061,12 +5046,12 @@ } }, "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz", + "integrity": "sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA==", "dev": true, "requires": { - "chokidar": "^2.0.2", + "chokidar": "^2.1.8", "graceful-fs": "^4.1.2", "neo-async": "^2.5.0" }, @@ -5158,9 +5143,9 @@ } }, "fsevents": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", - "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", + "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", "dev": true, "optional": true, "requires": { @@ -5213,7 +5198,7 @@ } }, "chownr": { - "version": "1.1.3", + "version": "1.1.4", "bundled": true, "dev": true, "optional": true @@ -5385,7 +5370,7 @@ } }, "minimist": { - "version": "0.0.8", + "version": "1.2.5", "bundled": true, "dev": true, "optional": true @@ -5410,12 +5395,12 @@ } }, "mkdirp": { - "version": "0.5.1", + "version": "0.5.3", "bundled": true, "dev": true, "optional": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "ms": { @@ -5425,7 +5410,7 @@ "optional": true }, "needle": { - "version": "2.4.0", + "version": "2.3.3", "bundled": true, "dev": true, "optional": true, @@ -5454,7 +5439,7 @@ } }, "nopt": { - "version": "4.0.1", + "version": "4.0.3", "bundled": true, "dev": true, "optional": true, @@ -5479,13 +5464,14 @@ "optional": true }, "npm-packlist": { - "version": "1.4.7", + "version": "1.4.8", "bundled": true, "dev": true, "optional": true, "requires": { "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" } }, "npmlog": { @@ -5565,18 +5551,10 @@ "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } } }, "readable-stream": { - "version": "2.3.6", + "version": "2.3.7", "bundled": true, "dev": true, "optional": true, @@ -5786,15 +5764,15 @@ } }, "webpack": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.0.tgz", - "integrity": "sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w==", + "version": "4.42.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.1.tgz", + "integrity": "sha512-SGfYMigqEfdGchGhFFJ9KyRpQKnipvEvjc1TwrXEPCM6H5Wywu10ka8o3KGrMzSMxMQKt8aCHUFh5DaQ9UmyRg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/wasm-edit": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", "acorn": "^6.2.1", "ajv": "^6.10.2", "ajv-keywords": "^3.4.1", @@ -5806,7 +5784,7 @@ "loader-utils": "^1.2.3", "memory-fs": "^0.4.1", "micromatch": "^3.1.10", - "mkdirp": "^0.5.1", + "mkdirp": "^0.5.3", "neo-async": "^2.6.1", "node-libs-browser": "^2.2.1", "schema-utils": "^1.0.0", @@ -5816,6 +5794,21 @@ "webpack-sources": "^1.4.1" }, "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", diff --git a/package.json b/package.json index 97c790fbe..a05851987 100644 --- a/package.json +++ b/package.json @@ -17,12 +17,12 @@ "npm-run-all": "^4.1.5", "sass-loader": "^8.0.2", "style-loader": "^1.1.3", - "webpack": "^4.42.0", + "webpack": "^4.42.1", "webpack-cli": "^3.3.11" }, "dependencies": { "clipboard": "^2.0.6", - "codemirror": "^5.52.0", + "codemirror": "^5.52.2", "dropzone": "^5.7.0", "markdown-it": "^10.0.0", "markdown-it-task-lists": "^2.1.1", From ef416d3e86e89bd856eead37fd9479a432ce8cda Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 4 Apr 2020 00:09:58 +0100 Subject: [PATCH 008/197] Fixed editor JavaScript error in TemplateManager - Caused when loading the editor with no templates in the system. - Tried to init a search box that did not exist. --- resources/js/components/template-manager.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/js/components/template-manager.js b/resources/js/components/template-manager.js index d004a4307..f8b19a40c 100644 --- a/resources/js/components/template-manager.js +++ b/resources/js/components/template-manager.js @@ -56,6 +56,10 @@ class TemplateManager { setupSearchBox() { const searchBox = this.elem.querySelector('.search-box'); + + // Search box may not exist if there are no existing templates in the system. + if (!searchBox) return; + const input = searchBox.querySelector('input'); const submitButton = searchBox.querySelector('button'); const cancelButton = searchBox.querySelector('button.search-box-cancel'); @@ -70,7 +74,7 @@ class TemplateManager { } performSearch = performSearch.bind(this); - // Searchbox enter press + // Search box enter press searchBox.addEventListener('keypress', event => { if (event.key === 'Enter') { event.preventDefault(); From 3500182c5ffaf103d320071060af4d8b5d53efa9 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 4 Apr 2020 00:48:32 +0100 Subject: [PATCH 009/197] Updated drawing uploads to use user id in image name - Instead of user name. - Due to issues with advanced charts like emoji zero-width-joiners. - Could also have security concerns on untrusted instances with certain webserver config due to double extension possibilities. Closes #1993 --- app/Uploads/ImageRepo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Uploads/ImageRepo.php b/app/Uploads/ImageRepo.php index 981c04673..b7a21809f 100644 --- a/app/Uploads/ImageRepo.php +++ b/app/Uploads/ImageRepo.php @@ -138,7 +138,7 @@ class ImageRepo */ public function saveDrawing(string $base64Uri, int $uploadedTo): Image { - $name = 'Drawing-' . user()->getShortName(40) . '-' . strval(time()) . '.png'; + $name = 'Drawing-' . strval(user()->id) . '-' . strval(time()) . '.png'; return $this->imageService->saveNewFromBase64Uri($base64Uri, $name, 'drawio', $uploadedTo); } From f84bf8e883e8e5bd9a24b908e2f90a2742d36d19 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 4 Apr 2020 01:16:05 +0100 Subject: [PATCH 010/197] Updated test files to be PSR-4 compliant Closes #1924 --- tests/Api/ApiAuthTest.php | 5 ++- tests/Api/ApiConfigTest.php | 7 ++-- tests/Api/ApiDocsTest.php | 4 +-- tests/Api/ApiListingTest.php | 5 ++- tests/Api/BooksApiTest.php | 3 +- tests/{ => Api}/TestsApi.php | 4 +-- tests/Auth/AuthTest.php | 3 +- tests/Auth/LdapTest.php | 3 +- tests/Auth/Saml2Test.php | 3 +- tests/Auth/SocialAuthTest.php | 3 +- tests/Auth/UserInviteTest.php | 3 +- tests/Entity/BookShelfTest.php | 3 +- tests/Entity/CommentSettingTest.php | 45 +++++++++++++++----------- tests/Entity/CommentTest.php | 3 +- tests/Entity/EntitySearchTest.php | 3 +- tests/Entity/EntityTest.php | 3 +- tests/Entity/ExportTest.php | 3 +- tests/Entity/MarkdownTest.php | 4 ++- tests/Entity/PageContentTest.php | 3 +- tests/Entity/PageDraftTest.php | 3 +- tests/Entity/PageRevisionTest.php | 2 +- tests/Entity/PageTemplateTest.php | 2 +- tests/Entity/SortTest.php | 3 +- tests/Entity/TagTest.php | 3 +- tests/Permissions/RestrictionsTest.php | 3 +- tests/Permissions/RolesTest.php | 3 +- tests/Unit/ConfigTest.php | 4 ++- tests/Unit/UrlTest.php | 4 ++- tests/Uploads/AttachmentTest.php | 3 +- tests/Uploads/UsesImages.php | 1 - tests/User/UserApiTokenTest.php | 2 +- tests/User/UserPreferencesTest.php | 4 ++- tests/User/UserProfileTest.php | 4 ++- 33 files changed, 89 insertions(+), 62 deletions(-) rename tests/{ => Api}/TestsApi.php (96%) diff --git a/tests/Api/ApiAuthTest.php b/tests/Api/ApiAuthTest.php index 1f283753a..302093947 100644 --- a/tests/Api/ApiAuthTest.php +++ b/tests/Api/ApiAuthTest.php @@ -1,10 +1,9 @@ -page = \BookStack\Entities\Page::first(); - } +class CommentSettingTest extends BrowserKitTest +{ + protected $page; - public function test_comment_disable () { - $this->asAdmin(); + public function setUp(): void + { + parent::setUp(); + $this->page = Page::first(); + } - $this->setSettings(['app-disable-comments' => 'true']); + public function test_comment_disable() + { + $this->asAdmin(); - $this->asAdmin()->visit($this->page->getUrl()) - ->pageNotHasElement('.comments-list'); - } + $this->setSettings(['app-disable-comments' => 'true']); - public function test_comment_enable () { - $this->asAdmin(); + $this->asAdmin()->visit($this->page->getUrl()) + ->pageNotHasElement('.comments-list'); + } - $this->setSettings(['app-disable-comments' => 'false']); + public function test_comment_enable() + { + $this->asAdmin(); - $this->asAdmin()->visit($this->page->getUrl()) - ->pageHasElement('.comments-list'); - } + $this->setSettings(['app-disable-comments' => 'false']); + + $this->asAdmin()->visit($this->page->getUrl()) + ->pageHasElement('.comments-list'); + } } \ No newline at end of file diff --git a/tests/Entity/CommentTest.php b/tests/Entity/CommentTest.php index 2b943f96f..a2126407b 100644 --- a/tests/Entity/CommentTest.php +++ b/tests/Entity/CommentTest.php @@ -1,7 +1,8 @@ - Date: Sun, 5 Apr 2020 13:07:19 +0100 Subject: [PATCH 011/197] Updated styles to use logical properties/values - Intended to improve RTL support in the interface. - Also adds hebrew to language dropdown since that was missing. Related to #1794 --- resources/js/components/dropdown.js | 9 +- resources/lang/en/settings.php | 1 + resources/sass/_blocks.scss | 12 +-- resources/sass/_buttons.scss | 16 ++-- resources/sass/_components.scss | 26 +++--- resources/sass/_forms.scss | 24 +++--- resources/sass/_header.scss | 68 +++++++++------ resources/sass/_layout.scss | 26 +++--- resources/sass/_lists.scss | 84 +++++++++++-------- resources/sass/_mixins.scss | 24 ++++++ resources/sass/_pages.scss | 50 ++--------- resources/sass/_spacing.scss | 8 +- resources/sass/_tables.scss | 4 +- resources/sass/_text.scss | 10 +-- resources/sass/print-styles.scss | 8 +- resources/sass/styles.scss | 18 ++-- .../views/auth/forms/login/saml2.blade.php | 2 +- resources/views/auth/login.blade.php | 2 +- resources/views/auth/register.blade.php | 2 +- resources/views/base.blade.php | 2 +- tests/LanguageTest.php | 16 +++- 21 files changed, 228 insertions(+), 184 deletions(-) diff --git a/resources/js/components/dropdown.js b/resources/js/components/dropdown.js index 4de1e239b..367c956ce 100644 --- a/resources/js/components/dropdown.js +++ b/resources/js/components/dropdown.js @@ -11,6 +11,7 @@ class DropDown { this.menu = elem.querySelector('.dropdown-menu, [dropdown-menu]'); this.moveMenu = elem.hasAttribute('dropdown-move-menu'); this.toggle = elem.querySelector('[dropdown-toggle]'); + this.direction = (document.dir === 'rtl') ? 'right' : 'left'; this.body = document.body; this.showing = false; this.setupListeners(); @@ -28,7 +29,11 @@ class DropDown { this.rect = this.menu.getBoundingClientRect(); this.body.appendChild(this.menu); this.menu.style.position = 'fixed'; - this.menu.style.left = `${this.rect.left}px`; + if (this.direction === 'right') { + this.menu.style.right = `${(this.rect.right - this.rect.width)}px`; + } else { + this.menu.style.left = `${this.rect.left}px`; + } this.menu.style.top = `${this.rect.top}px`; this.menu.style.width = `${this.rect.width}px`; } @@ -67,7 +72,7 @@ class DropDown { this.toggle.setAttribute('aria-expanded', 'false'); if (this.moveMenu) { this.menu.style.position = ''; - this.menu.style.left = ''; + this.menu.style[this.direction] = ''; this.menu.style.top = ''; this.menu.style.width = ''; this.container.appendChild(this.menu); diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index 35bb09cd4..f1345c743 100755 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/sass/_blocks.scss b/resources/sass/_blocks.scss index ff344158f..d02d25db4 100644 --- a/resources/sass/_blocks.scss +++ b/resources/sass/_blocks.scss @@ -3,7 +3,7 @@ * Callouts */ .callout { - border-left: 3px solid #BBB; + border-inline-start: 3px solid #BBB; background-color: #EEE; padding: $-s $-s $-s $-xl; display: block; @@ -109,7 +109,7 @@ background-color: #EEE; } .svg-icon { - margin-right: 0px; + margin-inline-end: 0px; } } > div .outline input { @@ -177,8 +177,8 @@ .content-wrap.card { padding: $-m $-xxl; - margin-left: auto; - margin-right: auto; + margin-inline-start: auto; + margin-inline-end: auto; margin-bottom: $-xl; overflow: initial; min-height: 60vh; @@ -211,7 +211,7 @@ .tag-item { display: inline-flex; margin-bottom: $-xs; - margin-right: $-xs; + margin-inline-end: $-xs; border-radius: 4px; border: 1px solid #CCC; overflow: hidden; @@ -229,7 +229,7 @@ fill: #888; } .tag-value { - border-left: 1px solid #DDD; + border-inline-start: 1px solid #DDD; background-color: rgba(255, 255, 255, 0.5); } } diff --git a/resources/sass/_buttons.scss b/resources/sass/_buttons.scss index e3d9e17ca..7df1d61a4 100644 --- a/resources/sass/_buttons.scss +++ b/resources/sass/_buttons.scss @@ -66,7 +66,7 @@ button { } .button + .button { - margin-left: $-s; + margin-inline-start: $-s; } .button.small { @@ -99,26 +99,28 @@ button { .button.block { width: 100%; - text-align: left; + text-align: start; display: block; } .button.icon { .svg-icon { - margin-right: 0; + margin-inline-end: 0; } } .button.svg { + display: flex; + align-items: center; + padding: $-s $-m; + padding-bottom: ($-s - 2px); svg { display: inline-block; - position: absolute; - left: $-m; - top: $-s - 2px; width: 24px; height: 24px; + bottom: auto; + margin-inline-end: $-m; } - padding: $-s $-m ($-s - 2px) ($-m*2 + 24px); } .button[disabled] { diff --git a/resources/sass/_components.scss b/resources/sass/_components.scss index 6ef53b719..f4ed45c2c 100644 --- a/resources/sass/_components.scss +++ b/resources/sass/_components.scss @@ -7,7 +7,7 @@ padding: $-m $-l; background-color: #FFF; border-radius: 4px; - border-left: 6px solid currentColor; + border-inline-start: 6px solid currentColor; box-shadow: $bs-large; z-index: 999999; cursor: pointer; @@ -26,7 +26,7 @@ svg { width: 2.8rem; height: 2.8rem; - padding-right: $-s; + padding-inline-end: $-s; fill: currentColor; } .dismiss { @@ -63,7 +63,7 @@ transition: all ease-in-out 180ms; user-select: none; svg[data-icon="caret-right"] { - margin-right: 0; + margin-inline-end: 0; font-size: 1rem; transition: all ease-in-out 180ms; transform: rotate(0deg); @@ -73,7 +73,7 @@ transform: rotate(90deg); } svg[data-icon="caret-right"] + * { - margin-left: $-xs; + margin-inline-start: $-xs; } } @@ -243,7 +243,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { width: 300px; overflow-y: auto; overflow-x: hidden; - border-left: 1px solid #DDD; + border-inline-start: 1px solid #DDD; .inner { padding: $-m; } @@ -477,7 +477,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { display: block; top: 50%; left: 50%; - margin-left: -27px; + margin-inline-start: -27px; margin-top: -35px; } @@ -511,7 +511,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { top: 50%; margin-top: -8px; width: 80px; - margin-left: -40px; + margin-inline-start: -40px; background: rgba(255, 255, 255, 0.9); transform: scale(1); border-radius: 8px; @@ -568,14 +568,14 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { left: 44px; width: 0; height: 0; - border-left: 6px solid transparent; - border-right: 6px solid transparent; + border-inline-start: 6px solid transparent; + border-inline-end: 6px solid transparent; border-bottom: 6px solid $negative; } .tab-container .nav-tabs { - text-align: left; + text-align: start; border-bottom: 1px solid #DDD; margin-bottom: $-m; .tab-item { @@ -613,7 +613,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { max-width: 480px; margin-bottom: $-s; a { - margin-right: $-xs; + margin-inline-end: $-xs; text-decoration: underline; } } @@ -659,7 +659,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { } a { color: #666; } span { - padding-left: $-xxs; + padding-inline-start: $-xxs; } } .text-muted { @@ -692,7 +692,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { height: 100%; display: flex; flex-direction: column; - border-left: 1px solid #DDD; + border-inline-start: 1px solid #DDD; } .template-item-actions button { cursor: pointer; diff --git a/resources/sass/_forms.scss b/resources/sass/_forms.scss index da0f7ef4c..f306a717b 100644 --- a/resources/sass/_forms.scss +++ b/resources/sass/_forms.scss @@ -107,15 +107,15 @@ } .markdown-display { - margin-left: -1px; + margin-inline-start: -1px; } .markdown-editor-display { background-color: #FFFFFF; body { background-color: #FFFFFF; - padding-left: 16px; - padding-right: 16px; + padding-inline-start: 16px; + pmargin-inline-end: 16px; } [drawio-diagram]:hover { outline: 2px solid var(--color-primary); @@ -155,12 +155,12 @@ label.radio, label.checkbox { font-weight: 400; user-select: none; input[type="radio"], input[type="checkbox"] { - margin-right: $-xs; + margin-inline-end: $-xs; } } label.inline.checkbox { - margin-right: $-m; + margin-inline-end: $-m; } label + p.small { @@ -288,12 +288,12 @@ input[type=color] { border: 1px solid #DDD; border-radius: 4px; .collapse-title { - margin-left: -$-m; - margin-right: -$-m; + margin-inline-start: -$-m; + margin-inline-end: -$-m; padding: $-s $-m; display: block; width: calc(100% + 32px); - text-align: left; + text-align: start; } .collapse-title, .collapse-title label { cursor: pointer; @@ -306,7 +306,7 @@ input[type=color] { .collapse-title label:before { display: inline-block; content: '▸'; - margin-right: $-m; + margin-inline-end: $-m; transition: all ease-in-out 400ms; transform: rotate(0); } @@ -373,10 +373,14 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] { position: absolute; left: 8px; top: 9px; + @include rtl { + right: 8px; + left: auto; + } } input { display: block; - padding-left: $-l + 4px; + padding-inline-start: $-l + 4px; width: 300px; max-width: 100%; } diff --git a/resources/sass/_header.scss b/resources/sass/_header.scss index 687ddd8d2..5503a0895 100644 --- a/resources/sass/_header.scss +++ b/resources/sass/_header.scss @@ -34,8 +34,8 @@ header { fill: #FFF; } .dropdown-container { - padding-left: $-m; - padding-right: 0; + padding-inline-start: $-m; + padding-inline-end: 0; } .avatar, .user-name { display: inline-block; @@ -53,7 +53,7 @@ header { vertical-align: top; } > span { - padding-left: $-xs; + padding-inline-start: $-xs; display: inline-block; padding-top: $-xxs; } @@ -62,7 +62,7 @@ header { font-size: 18px; } @include between($l, $xl) { - padding-left: $-xs; + padding-inline-start: $-xs; .name { display: none; } @@ -87,7 +87,7 @@ header .search-box { border-radius: 40px; color: #EEE; z-index: 2; - padding-left: 40px; + padding-inline-start: 40px; &:focus { outline: none; border: 1px solid rgba(255, 255, 255, 0.6); @@ -97,8 +97,12 @@ header .search-box { fill: #EEE; z-index: 1; left: 16px; + @include rtl { + left: auto; + right: 16px; + } svg { - margin-right: 0; + margin-block-end: 0; } } ::-webkit-input-placeholder { /* Chrome/Opera/Safari */ @@ -124,12 +128,12 @@ header .search-box { font-size: 1.8em; color: #fff; font-weight: 400; - padding: 14px $-l 14px 0; + @include padding(14px, $-l, 14px, 0); vertical-align: top; line-height: 1; } .logo-image { - margin: $-xs $-s $-xs 0; + @include margin($-xs, $-s, $-xs, 0); vertical-align: top; height: 43px; } @@ -151,8 +155,14 @@ header .search-box { margin: 0; bottom: -2px; } + @include rtl() { + left: $-m; + right: auto; + } } + + @include smaller-than($l) { header .header-links { display: none; @@ -169,13 +179,13 @@ header .search-box { } } header .links a, header .dropdown-container ul li a { - text-align: left; + text-align: start; display: block; padding: $-s $-m; color: $text-dark; fill: $text-dark; svg { - margin-right: $-s; + margin-inline-end: $-s; } &:hover { background-color: #EEE; @@ -186,7 +196,7 @@ header .search-box { } header .dropdown-container { display: block; - padding-left: 0; + padding-inline-start: 0; } header .links { display: block; @@ -215,7 +225,7 @@ header .search-box { border-bottom: 3px solid #BBB; cursor: pointer; &:first-child { - border-right: 1px solid #DDD; + border-inline-end: 1px solid #DDD; } &.active { border-bottom-color: currentColor; @@ -253,7 +263,7 @@ header .search-box { display: none; } > span:first-child { - margin-right: 0; + margin-block-end: 0; } } } @@ -269,7 +279,7 @@ header .search-box { } } .svg-icon { - margin-right: 0; + margin-block-end: 0; } } @@ -282,9 +292,17 @@ header .search-box { position: absolute; z-index: 80; right: -$-m; + @include rtl { + right: auto; + left: -$-m; + } .breadcrumb-listing-search .svg-icon { position: absolute; left: $-s; + @include rtl { + right: $-s; + left: auto; + } top: 11px; fill: #888; pointer-events: none; @@ -292,10 +310,10 @@ header .search-box { .breadcrumb-listing-entity-list { max-height: 400px; overflow-y: scroll; - text-align: left; + text-align: start; } input { - padding-left: $-xl; + padding-inline-start: $-xl; border-radius: 0; border: 0; border-bottom: 1px solid #DDD; @@ -337,25 +355,25 @@ header .search-box { display: inline-block; padding: $-xs $-s; &:last-child { - padding-right: 0; + padding-inline-end: 0; } &:first-child { - padding-left: 0; + padding-inline-start: 0; } } .action-buttons .dropdown-container:last-child a { - padding-right: 0; - padding-left: $-s; + padding-inline-end: 0; + padding-inline-start: $-s; } .action-buttons { - text-align: right; + text-align: end; &.text-left { - text-align: left; + text-align: start; .text-button { - padding-right: $-m; - padding-left: 0; + padding-inline-end: $-m; + padding-inline-start: 0; } } &.text-center { @@ -368,6 +386,6 @@ header .search-box { padding: $-xs $-xs; } .action-buttons .dropdown-container:last-child a { - padding-left: $-xs; + padding-inline-start: $-xs; } } \ No newline at end of file diff --git a/resources/sass/_layout.scss b/resources/sass/_layout.scss index a280e4ed1..197d5271b 100644 --- a/resources/sass/_layout.scss +++ b/resources/sass/_layout.scss @@ -4,10 +4,10 @@ */ .container { max-width: $xxl; - margin-left: auto; - margin-right: auto; - padding-left: $-m; - padding-right: $-m; + margin-inline-start: auto; + margin-inline-end: auto; + padding-inline-start: $-m; + padding-inline-end: $-m; &.small { max-width: 840px; } @@ -198,8 +198,8 @@ body.flexbox { */ .tri-layout-container { display: grid; - margin-left: $-xl; - margin-right: $-xl; + margin-inline-start: $-xl; + margin-inline-end: $-xl; grid-template-columns: 1fr 4fr 1fr; grid-template-areas: "a b c"; grid-column-gap: $-xxl; @@ -223,7 +223,7 @@ body.flexbox { ". b b"; grid-template-columns: 1fr 3fr; grid-template-rows: min-content min-content 1fr; - padding-right: $-l; + padding-inline-end: $-l; } } @include between($l, $xxl) { @@ -258,11 +258,11 @@ body.flexbox { grid-template-areas: none; grid-template-columns: 1fr; grid-column-gap: 0; - padding-right: $-xs; - padding-left: $-xs; + padding-inline-end: $-xs; + padding-inline-start: $-xs; .tri-layout-left-contents, .tri-layout-right-contents { - padding-left: $-m; - padding-right: $-m; + padding-inline-start: $-m; + padding-inline-end: $-m; } .tri-layout-left > *, .tri-layout-right > * { display: none; @@ -316,7 +316,7 @@ body.flexbox { @include smaller-than($m) { .tri-layout-container { - margin-left: 0; - margin-right: 0; + margin-inline-start: 0; + margin-inline-end: 0; } } \ No newline at end of file diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 2e8fa257a..7beb63d4e 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -6,7 +6,7 @@ justify-self: stretch; align-self: stretch; height: auto; - margin-right: $-l; + margin-inline-end: $-l; } .icon:after { opacity: 0.5; @@ -60,7 +60,7 @@ border-radius: 0 4px 4px 0; padding: $-xs $-m; width: 100%; - text-align: left; + text-align: start; } .chapter-expansion-toggle:hover { background-color: rgba(0, 0, 0, 0.06); @@ -88,13 +88,17 @@ .sidebar-page-nav { $nav-indent: $-m; list-style: none; - margin: $-s 0 $-m $-xs; + @include margin($-s, 0, $-m, $-xs); position: relative; &:after { content: ''; display: block; position: absolute; left: 0; + @include rtl { + left: auto; + right: 0; + } background-color: rgba(0, 0, 0, 0.2); width: 2px; top: 5px; @@ -107,22 +111,22 @@ position: relative; } .h1 { - padding-left: $nav-indent; + padding-inline-start: $nav-indent; } .h2 { - padding-left: $nav-indent * 1.5; + padding-inline-start: $nav-indent * 1.5; } .h3 { - padding-left: $nav-indent * 2; + padding-inline-start: $nav-indent * 2; } .h4 { - padding-left: $nav-indent * 2.5; + padding-inline-start: $nav-indent * 2.5; } .h5 { - padding-left: $nav-indent*3; + padding-inline-start: $nav-indent*3; } .h6 { - padding-left: $nav-indent*3.5; + padding-inline-start: $nav-indent*3.5; } .current-heading { font-weight: bold; @@ -139,15 +143,19 @@ border-radius: 50%; box-shadow: 0 0 0 6px #F2F2F2; z-index: 1; + @include rtl { + left: auto; + right: -2px; + } } } // Sidebar list .book-tree .sidebar-page-list { list-style: none; - margin: $-xs -$-s 0 -$-s; - padding-left: 0; - padding-right: 0; + @include margin($-xs, -$-s, 0, -$-s); + padding-inline-start: 0; + padding-inline-end: 0; position: relative; &:after, .sub-menu:after { @@ -157,14 +165,18 @@ left: $-m; top: 1rem; bottom: 1rem; - border-left: 4px solid rgba(0, 0, 0, 0.1); + border-inline-start: 4px solid rgba(0, 0, 0, 0.1); z-index: 0; + @include rtl { + left: auto; + right: $-m; + } } ul { list-style: none; - padding-left: 1rem; - padding-right: 0; + padding-inline-start: 1rem; + padding-inline-end: 0; } .entity-list-item { @@ -183,7 +195,7 @@ } .entity-list-item.no-hover { margin-top: -$-xs; - padding-right: 0; + padding-inline-end: 0; } .entity-list-item-name { font-size: 1em; @@ -192,10 +204,10 @@ .chapter-child-menu { font-size: .8rem; margin-top: -.2rem; - margin-left: -1rem; + margin-inline-start: -1rem; } [chapter-toggle] { - padding-left: .7rem; + padding-inline-start: .7rem; padding-bottom: .2rem; } .entity-list-item .icon { @@ -218,7 +230,7 @@ .chapter-child-menu { ul.sub-menu { display: none; - padding-left: 0; + padding-inline-start: 0; position: relative; } [chapter-toggle].open + .sub-menu { @@ -254,10 +266,10 @@ justify-content: space-between; } .sort-box-options .button { - margin-left: 0; + margin-inline-start: 0; } .sortable-page-list { - margin-left: 0; + margin-inline-start: 0; padding: 0; .entity-list-item > span:first-child { align-self: flex-start; @@ -267,12 +279,12 @@ flex: 1; } > ul { - margin-left: 0; + margin-inline-start: 0; } ul { margin-bottom: $-m; margin-top: 0; - padding-left: $-m; + padding-inline-start: $-m; } li { border: 1px solid #DDD; @@ -280,7 +292,7 @@ min-height: 38px; } li.text-page, li.text-chapter { - border-left: 2px solid currentColor; + border-inline-start: 2px solid currentColor; } li:first-child { margin-top: $-xs; @@ -320,7 +332,7 @@ ul.pagination { display: inline-block; list-style: none; margin: $-m 0; - padding-left: 1px; + padding-inline-start: 1px; li { float: left; } @@ -338,7 +350,7 @@ ul.pagination { display: block; padding: $-xxs $-s; border: 1px solid #CCC; - margin-left: -1px; + margin-inline-start: -1px; user-select: none; &.disabled { cursor: not-allowed; @@ -402,13 +414,13 @@ ul.pagination { color: #666; } > span:first-child { - margin-right: $-m; + margin-inline-end: $-m; flex-basis: 1.88em; flex: none; } > span:last-child { flex: 1; - text-align: left; + text-align: start; } &:not(.no-hover) { cursor: pointer; @@ -438,7 +450,7 @@ ul.pagination { position: relative; top: 1px; svg { - margin-right: 0; + margin-inline-end: 0; } } @@ -460,7 +472,7 @@ ul.pagination { text-overflow: ellipsis; height: 2.5em; overflow: hidden; - text-align: left; + text-align: start; display: block; white-space: nowrap; } @@ -474,7 +486,7 @@ ul.pagination { background-position: 50% 50%; border-radius: 3px; position: relative; - margin-right: $-l; + margin-inline-end: $-l; &.entity-list-item-image-wide { width: 220px; @@ -484,7 +496,7 @@ ul.pagination { color: #FFF; fill: #FFF; font-size: 1.66rem; - margin-right: 0; + margin-inline-end: 0; position: absolute; bottom: $-xs; left: $-xs; @@ -550,7 +562,7 @@ ul.pagination { padding: $-xs 0; color: #555; fill: #555; - text-align: left !important; + text-align: start !important; &.wide { min-width: 220px; } @@ -577,14 +589,14 @@ ul.pagination { outline-offset: -2px; } svg { - margin-right: $-s; + margin-inline-end: $-s; display: inline-block; width: 16px; } } button { width: 100%; - text-align: left; + text-align: start; } li.border-bottom { border-bottom: 1px solid #DDD; @@ -615,7 +627,7 @@ ul.pagination { color: #FFF; fill: #FFF; font-size: 2rem; - margin-right: 0; + margin-inline-end: 0; position: absolute; bottom: 10px; left: 6px; diff --git a/resources/sass/_mixins.scss b/resources/sass/_mixins.scss index 1c45ebd30..8a6becf6b 100644 --- a/resources/sass/_mixins.scss +++ b/resources/sass/_mixins.scss @@ -8,3 +8,27 @@ @mixin between($min, $max) { @media screen and (min-width: $min) and (max-width: $max) { @content; } } + +// Padding shorthand using logical operators to better support RTL. +@mixin padding($t, $r, $b, $l) { + padding-block-start: $t; + padding-block-end: $b; + padding-inline-start: $l; + padding-inline-end: $r; +} + +// Margin shorthand using logical operators to better support RTL. +@mixin margin($t, $r, $b, $l) { + margin-block-start: $t; + margin-block-end: $b; + margin-inline-start: $l; + margin-inline-end: $r; +} + +// Create a RTL specific style block. +// Mostly used as a patch until browser support improves for logical properties. +@mixin rtl() { + html[dir=rtl] & { + @content; + } +} \ No newline at end of file diff --git a/resources/sass/_pages.scss b/resources/sass/_pages.scss index 9281a2194..701905165 100755 --- a/resources/sass/_pages.scss +++ b/resources/sass/_pages.scss @@ -59,7 +59,7 @@ body.mce-fullscreen, body.markdown-fullscreen { text-align: center; svg { fill: #FFF; - margin-right: 0; + margin-inline-end: 0; } } @@ -174,14 +174,14 @@ body.mce-fullscreen, body.markdown-fullscreen { bottom: -9px; width: 16px; height: 16px; - margin-left: -8px; + margin-inline-start: -8px; content: ''; display: block; background-color:#FFF; transform: rotate(45deg); transform-origin: 50% 50%; - border-bottom: 1px solid #CCC; - border-right: 1px solid #CCC; + border-inline-startom: 1px solid #CCC; + border-inline-end: 1px solid #CCC; z-index: 56; } input, button, a { @@ -255,7 +255,7 @@ body.mce-fullscreen, body.markdown-fullscreen { } .tabs { display: block; - border-right: 1px solid #DDD; + border-inline-end: 1px solid #DDD; width: 48px; flex: 0 1 auto; } @@ -294,8 +294,8 @@ body.mce-fullscreen, body.markdown-fullscreen { width: 100%; min-width: 50px; } - .tags td, .tag-table > div > div > div { - padding-right: $-s; + .tags td, .inline-start-table > div > div > div { + padding-inline-end: $-s; padding-top: $-s; position: relative; } @@ -319,42 +319,6 @@ body.mce-fullscreen, body.markdown-fullscreen { display: none; } -.tag-display { - position: relative; - table { - width: 100%; - margin: 0; - padding: 0; - } - tr:first-child td { - padding-top: 0; - } - .heading th { - padding: $-xs $-s; - color: rgba(100, 100, 100, 0.7); - border: 0; - font-weight: 400; - } - td { - border: 0; - border-bottom: 1px solid #EEE; - padding: $-xs $-s; - color: #444; - } - tr td:first-child { - padding-left:0; - } - .tag-value { - color: #888; - } - tr:last-child td { - border-bottom: none; - } - .tag { - padding: $-s; - } -} - .suggestion-box { position: absolute; background-color: #FFF; diff --git a/resources/sass/_spacing.scss b/resources/sass/_spacing.scss index 69ed5a2d3..57b229ab8 100644 --- a/resources/sass/_spacing.scss +++ b/resources/sass/_spacing.scss @@ -7,8 +7,8 @@ #{$prop}: $size !important; } .#{$propLetter}x-#{$sizeLetter} { - #{$prop}-left: $size !important; - #{$prop}-right: $size !important; + #{$prop}-inline-start: $size !important; + #{$prop}-inline-end: $size !important; } .#{$propLetter}y-#{$sizeLetter} { #{$prop}-top: $size !important; @@ -18,13 +18,13 @@ #{$prop}-top: $size !important; } .#{$propLetter}r-#{$sizeLetter} { - #{$prop}-right: $size !important; + #{$prop}-inline-end: $size !important; } .#{$propLetter}b-#{$sizeLetter} { #{$prop}-bottom: $size !important; } .#{$propLetter}l-#{$sizeLetter} { - #{$prop}-left: $size !important; + #{$prop}-inline-start: $size !important; } } } diff --git a/resources/sass/_tables.scss b/resources/sass/_tables.scss index a1a2fef0a..277873608 100644 --- a/resources/sass/_tables.scss +++ b/resources/sass/_tables.scss @@ -23,7 +23,7 @@ table.table { border-bottom: 1px solid rgba(0, 0, 0, 0.05); } th, td { - text-align: left; + text-align: start; border: none; padding: $-s $-s; vertical-align: middle; @@ -36,7 +36,7 @@ table.table { background-color: #EEE; } .text-right { - text-align: right; + text-align: end; } .text-center { text-align: center; diff --git a/resources/sass/_text.scss b/resources/sass/_text.scss index 8210d6d44..00fc772cc 100644 --- a/resources/sass/_text.scss +++ b/resources/sass/_text.scss @@ -313,10 +313,10 @@ li > ol, li > ul { text-align: center; } .text-left { - text-align: left; + text-align: start; } .text-right { - text-align: right; + text-align: end; } @each $sizeLetter, $size in $screen-sizes { @@ -325,10 +325,10 @@ li > ol, li > ul { text-align: center; } .text-#{$sizeLetter}-left { - text-align: left; + text-align: start; } .text-#{$sizeLetter}-right { - text-align: right; + text-align: end; } } } @@ -384,6 +384,6 @@ span.sep { display: inline-block; position: relative; bottom: -0.105em; - margin-right: $-xs; + margin-inline-end: $-xs; pointer-events: none; } diff --git a/resources/sass/print-styles.scss b/resources/sass/print-styles.scss index 296afbe76..5cbd7f9d5 100644 --- a/resources/sass/print-styles.scss +++ b/resources/sass/print-styles.scss @@ -20,8 +20,8 @@ html, body { .tri-layout-container { grid-template-columns: 1fr; grid-template-areas: "b"; - margin-left: 0; - margin-right: 0; + margin-inline-start: 0; + margin-inline-end: 0; display: block; } @@ -30,6 +30,6 @@ html, body { } .content-wrap.card { - padding-left: 0; - padding-right: 0; + padding-inline-start: 0; + padding-inline-end: 0; } \ No newline at end of file diff --git a/resources/sass/styles.scss b/resources/sass/styles.scss index 1f4d00f6b..09d8b4100 100644 --- a/resources/sass/styles.scss +++ b/resources/sass/styles.scss @@ -74,7 +74,7 @@ $loadingSize: 10px; animation-duration: 1.4s; animation-iteration-count: infinite; animation-timing-function: cubic-bezier(.62, .28, .23, .99); - margin-right: 4px; + margin-inline-end: 4px; background-color: var(--color-page); animation-delay: 0.3s; } @@ -89,7 +89,7 @@ $loadingSize: 10px; animation-delay: 0.6s; } > span { - margin-left: $-s; + margin-inline-start: $-s; font-style: italic; color: #888; vertical-align: top; @@ -110,7 +110,7 @@ $btt-size: 40px; svg { width: $btt-size / 1.5; height: $btt-size / 1.5; - margin-right: 4px; + margin-inline-end: 4px; } width: $btt-size; height: $btt-size; @@ -138,7 +138,7 @@ $btt-size: 40px; input, button { border-radius: 0; border: 1px solid #DDD; - margin-left: -1px; + margin-inline-start: -1px; } input { flex: 5; @@ -177,8 +177,8 @@ $btt-size: 40px; overflow-y: scroll; height: 400px; background-color: #EEEEEE; - margin-right: 0; - margin-left: 0; + margin-inline-end: 0; + margin-inline-start: 0; } .entity-list-item { background-color: #FFF; @@ -252,7 +252,7 @@ $btt-size: 40px; } .list-sort { display: inline-grid; - margin-left: $-s; + margin-inline-start: $-s; grid-template-columns: minmax(120px, max-content) 40px; font-size: 0.9rem; border: 2px solid #DDD; @@ -264,14 +264,14 @@ $btt-size: 40px; color: #555; } .list-sort-type { - text-align: left; + text-align: start; } .list-sort-type, .list-sort-dir { padding: $-xs $-s; cursor: pointer; } .list-sort-dir { - border-left: 2px solid #DDD; + border-inline-start: 2px solid #DDD; fill: #888; .svg-icon { transition: transform ease-in-out 120ms; diff --git a/resources/views/auth/forms/login/saml2.blade.php b/resources/views/auth/forms/login/saml2.blade.php index aa1913e31..7d6595894 100644 --- a/resources/views/auth/forms/login/saml2.blade.php +++ b/resources/views/auth/forms/login/saml2.blade.php @@ -4,7 +4,7 @@
diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 0a21a0f62..868e0555f 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -17,7 +17,7 @@ @endforeach diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index 1625ebc4c..34aa81d7b 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -44,7 +44,7 @@ @endforeach diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index 075481620..d362ef373 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -1,5 +1,5 @@ - + {{ isset($pageTitle) ? $pageTitle . ' | ' : '' }}{{ setting('app-name') }} diff --git a/tests/LanguageTest.php b/tests/LanguageTest.php index d7654b867..d5c6e4532 100644 --- a/tests/LanguageTest.php +++ b/tests/LanguageTest.php @@ -11,7 +11,7 @@ class LanguageTest extends TestCase public function setUp(): void { parent::setUp(); - $this->langs = array_diff(scandir(resource_path('lang')), ['..', '.', 'check.php', 'format.php']); + $this->langs = array_diff(scandir(resource_path('lang')), ['..', '.']); } public function test_locales_config_key_set_properly() @@ -22,6 +22,20 @@ class LanguageTest extends TestCase $this->assertEquals(implode(':', $configLocales), implode(':', $this->langs), 'app.locales configuration variable does not match those found in lang files'); } + // Not part of standard phpunit test runs since we sometimes expect non-added langs. + public function do_test_locales_all_have_language_dropdown_entry() + { + $dropdownLocales = array_keys(trans('settings.language_select', [], 'en')); + sort($dropdownLocales); + sort($this->langs); + $diffs = array_diff($this->langs, $dropdownLocales); + if (count($diffs) > 0) { + $diffText = implode(',', $diffs); + $this->addWarning("Languages: {$diffText} found in files but not in language select dropdown."); + } + $this->assertTrue(true); + } + public function test_correct_language_if_not_logged_in() { $loginReq = $this->get('/login'); From fb08194af11e7915e1682cdd52395e008682c461 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 5 Apr 2020 14:12:23 +0100 Subject: [PATCH 012/197] New Crowdin translations (#2004) * New translations errors.php (Russian) * New translations settings.php (Portuguese, Brazilian) * New translations auth.php (Russian) * New translations entities.php (Russian) * New translations settings.php (Russian) * New translations settings.php (Slovak) * New translations settings.php (Persian) * New translations settings.php (Portuguese) * New translations settings.php (Polish) * New translations settings.php (Korean) * New translations settings.php (Swedish) * New translations validation.php (Swedish) * New translations errors.php (Turkish) * New translations settings.php (Turkish) * New translations entities.php (Swedish) * New translations settings.php (Ukrainian) * New translations errors.php (Swedish) * New translations entities.php (Slovenian) * New translations errors.php (Slovenian) * New translations pagination.php (Slovenian) * New translations passwords.php (Slovenian) * New translations settings.php (Slovenian) * New translations validation.php (Slovenian) * New translations settings.php (Spanish) * New translations settings.php (Spanish, Argentina) * New translations settings.php (Czech) * New translations pagination.php (Danish) * New translations settings.php (Danish) * New translations settings.php (Dutch) * New translations settings.php (Arabic) * New translations settings.php (Chinese Simplified) * New translations settings.php (Chinese Traditional) * New translations settings.php (Hungarian) * New translations errors.php (French) * New translations errors.php (Italian) * New translations settings.php (Italian) * New translations settings.php (Japanese) * New translations settings.php (French) * New translations errors.php (German) * New translations settings.php (German) * New translations settings.php (Hebrew) * New translations auth.php (Hebrew) * New translations validation.php (Hebrew) * New translations errors.php (Hebrew) * New translations entities.php (Hebrew) * New translations common.php (Hebrew) * New translations settings.php (German Informal) * New translations errors.php (German Informal) * New translations settings.php (Vietnamese) --- resources/lang/ar/settings.php | 1 + resources/lang/cs/settings.php | 1 + resources/lang/da/pagination.php | 12 + resources/lang/da/settings.php | 1 + resources/lang/de/errors.php | 4 +- resources/lang/de/settings.php | 1 + resources/lang/de_informal/errors.php | 4 +- resources/lang/de_informal/settings.php | 1 + resources/lang/es/settings.php | 1 + resources/lang/es_AR/settings.php | 1 + resources/lang/fa/settings.php | 1 + resources/lang/fr/errors.php | 2 +- resources/lang/fr/settings.php | 1 + resources/lang/he/auth.php | 10 + resources/lang/he/common.php | 7 + resources/lang/he/entities.php | 10 + resources/lang/he/errors.php | 19 ++ resources/lang/he/settings.php | 79 +++++++ resources/lang/he/validation.php | 91 +++++--- resources/lang/hu/settings.php | 1 + resources/lang/it/errors.php | 8 +- resources/lang/it/settings.php | 7 +- resources/lang/ja/settings.php | 1 + resources/lang/ko/settings.php | 1 + resources/lang/nl/settings.php | 1 + resources/lang/pl/settings.php | 1 + resources/lang/pt/settings.php | 1 + resources/lang/pt_BR/settings.php | 1 + resources/lang/ru/auth.php | 2 +- resources/lang/ru/entities.php | 2 +- resources/lang/ru/errors.php | 2 +- resources/lang/ru/settings.php | 1 + resources/lang/sk/settings.php | 1 + resources/lang/sl/entities.php | 164 ++++++------- resources/lang/sl/errors.php | 144 ++++++------ resources/lang/sl/pagination.php | 4 +- resources/lang/sl/passwords.php | 10 +- resources/lang/sl/settings.php | 295 ++++++++++++------------ resources/lang/sl/validation.php | 156 ++++++------- resources/lang/sv/entities.php | 24 +- resources/lang/sv/errors.php | 30 +-- resources/lang/sv/settings.php | 85 +++---- resources/lang/sv/validation.php | 42 ++-- resources/lang/tr/errors.php | 18 +- resources/lang/tr/settings.php | 60 ++--- resources/lang/uk/settings.php | 1 + resources/lang/vi/settings.php | 1 + resources/lang/zh_CN/settings.php | 3 +- resources/lang/zh_TW/settings.php | 1 + 49 files changed, 756 insertions(+), 559 deletions(-) create mode 100644 resources/lang/da/pagination.php diff --git a/resources/lang/ar/settings.php b/resources/lang/ar/settings.php index dcb7a2599..56b0a51be 100755 --- a/resources/lang/ar/settings.php +++ b/resources/lang/ar/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/cs/settings.php b/resources/lang/cs/settings.php index 16f146172..e36a53009 100644 --- a/resources/lang/cs/settings.php +++ b/resources/lang/cs/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/da/pagination.php b/resources/lang/da/pagination.php new file mode 100644 index 000000000..85bd12fc3 --- /dev/null +++ b/resources/lang/da/pagination.php @@ -0,0 +1,12 @@ + '« Previous', + 'next' => 'Next »', + +]; diff --git a/resources/lang/da/settings.php b/resources/lang/da/settings.php index 5bed76f35..8427d3722 100644 --- a/resources/lang/da/settings.php +++ b/resources/lang/da/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/de/errors.php b/resources/lang/de/errors.php index 4c795421c..205a8a632 100644 --- a/resources/lang/de/errors.php +++ b/resources/lang/de/errors.php @@ -83,7 +83,7 @@ return [ // Error pages '404_page_not_found' => 'Seite nicht gefunden', 'sorry_page_not_found' => 'Entschuldigung. Die Seite, die Sie angefordert haben, wurde nicht gefunden.', - 'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.', + 'sorry_page_not_found_permission_warning' => 'Wenn Sie erwartet haben, dass diese Seite existiert, haben Sie möglicherweise nicht die Berechtigung, sie anzuzeigen.', 'return_home' => 'Zurück zur Startseite', 'error_occurred' => 'Es ist ein Fehler aufgetreten', 'app_down' => ':appName befindet sich aktuell im Wartungsmodus.', @@ -98,6 +98,6 @@ return [ 'api_user_token_expired' => 'Das verwendete Autorisierungs-Token ist abgelaufen', // Settings & Maintenance - 'maintenance_test_email_failure' => 'Error thrown when sending a test email:', + 'maintenance_test_email_failure' => 'Fehler beim Senden einer Test E-Mail:', ]; diff --git a/resources/lang/de/settings.php b/resources/lang/de/settings.php index 9b21da6e6..263c0f923 100644 --- a/resources/lang/de/settings.php +++ b/resources/lang/de/settings.php @@ -204,6 +204,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/de_informal/errors.php b/resources/lang/de_informal/errors.php index b295ca554..3707dbf13 100644 --- a/resources/lang/de_informal/errors.php +++ b/resources/lang/de_informal/errors.php @@ -83,7 +83,7 @@ return [ // Error pages '404_page_not_found' => 'Seite nicht gefunden', 'sorry_page_not_found' => 'Entschuldigung. Die Seite, die Du angefordert hast, wurde nicht gefunden.', - 'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.', + 'sorry_page_not_found_permission_warning' => 'Wenn du erwartet hast, dass diese Seite existiert, hast du möglicherweise nicht die Berechtigung, sie anzuzeigen.', 'return_home' => 'Zurück zur Startseite', 'error_occurred' => 'Es ist ein Fehler aufgetreten', 'app_down' => ':appName befindet sich aktuell im Wartungsmodus.', @@ -98,6 +98,6 @@ return [ 'api_user_token_expired' => 'Das verwendete Autorisierungs-Token ist abgelaufen', // Settings & Maintenance - 'maintenance_test_email_failure' => 'Error thrown when sending a test email:', + 'maintenance_test_email_failure' => 'Fehler beim Senden einer Test E-Mail:', ]; diff --git a/resources/lang/de_informal/settings.php b/resources/lang/de_informal/settings.php index c0b5c5185..9af19031d 100644 --- a/resources/lang/de_informal/settings.php +++ b/resources/lang/de_informal/settings.php @@ -204,6 +204,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slowenisch', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/es/settings.php b/resources/lang/es/settings.php index ef074021b..57b91d033 100644 --- a/resources/lang/es/settings.php +++ b/resources/lang/es/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/es_AR/settings.php b/resources/lang/es_AR/settings.php index 4ed4d25af..f218dd95c 100644 --- a/resources/lang/es_AR/settings.php +++ b/resources/lang/es_AR/settings.php @@ -202,6 +202,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/fa/settings.php b/resources/lang/fa/settings.php index 46ad7b578..35bb09cd4 100644 --- a/resources/lang/fa/settings.php +++ b/resources/lang/fa/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/fr/errors.php b/resources/lang/fr/errors.php index de0d28efd..2c697e67d 100644 --- a/resources/lang/fr/errors.php +++ b/resources/lang/fr/errors.php @@ -83,7 +83,7 @@ return [ // Error pages '404_page_not_found' => 'Page non trouvée', 'sorry_page_not_found' => 'Désolé, cette page n\'a pas pu être trouvée.', - 'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.', + 'sorry_page_not_found_permission_warning' => 'Si vous vous attendiez à ce que cette page existe, il se peut que vous n\'ayez pas l\'autorisation de la consulter.', 'return_home' => 'Retour à l\'accueil', 'error_occurred' => 'Une erreur est survenue', 'app_down' => ':appName n\'est pas en service pour le moment', diff --git a/resources/lang/fr/settings.php b/resources/lang/fr/settings.php index 5f4c13e10..ab56d8ea2 100644 --- a/resources/lang/fr/settings.php +++ b/resources/lang/fr/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/he/auth.php b/resources/lang/he/auth.php index 37acb5698..8a982db01 100644 --- a/resources/lang/he/auth.php +++ b/resources/lang/he/auth.php @@ -64,4 +64,14 @@ return [ 'email_not_confirmed_click_link' => 'יש ללחוץ על הקישור אשר נשלח אליך לאחר ההרשמה', 'email_not_confirmed_resend' => 'אם אינך מוצא את המייל, ניתן לשלוח בשנית את האימות על ידי לחיצה על הכפתור למטה', 'email_not_confirmed_resend_button' => 'שלח שוב מייל אימות', + + // User Invite + 'user_invite_email_subject' => 'You have been invited to join :appName!', + 'user_invite_email_greeting' => 'An account has been created for you on :appName.', + 'user_invite_email_text' => 'Click the button below to set an account password and gain access:', + 'user_invite_email_action' => 'Set Account Password', + 'user_invite_page_welcome' => 'Welcome to :appName!', + 'user_invite_page_text' => 'To finalise your account and gain access you need to set a password which will be used to log-in to :appName on future visits.', + 'user_invite_page_confirm_button' => 'Confirm Password', + 'user_invite_success' => 'Password set, you now have access to :appName!' ]; \ No newline at end of file diff --git a/resources/lang/he/common.php b/resources/lang/he/common.php index 8459e1239..55c50bfb9 100644 --- a/resources/lang/he/common.php +++ b/resources/lang/he/common.php @@ -38,8 +38,13 @@ return [ 'reset' => 'איפוס', 'remove' => 'הסר', 'add' => 'הוסף', + 'fullscreen' => 'Fullscreen', // Sort Options + 'sort_options' => 'Sort Options', + 'sort_direction_toggle' => 'Sort Direction Toggle', + 'sort_ascending' => 'Sort Ascending', + 'sort_descending' => 'Sort Descending', 'sort_name' => 'שם', 'sort_created_at' => 'תאריך יצירה', 'sort_updated_at' => 'תאריך עדכון', @@ -55,8 +60,10 @@ return [ 'grid_view' => 'תצוגת רשת', 'list_view' => 'תצוגת רשימה', 'default' => 'ברירת מחדל', + 'breadcrumb' => 'Breadcrumb', // Header + 'profile_menu' => 'Profile Menu', 'view_profile' => 'הצג פרופיל', 'edit_profile' => 'ערוך פרופיל', diff --git a/resources/lang/he/entities.php b/resources/lang/he/entities.php index 0b5018462..2fb0e82ec 100644 --- a/resources/lang/he/entities.php +++ b/resources/lang/he/entities.php @@ -176,6 +176,7 @@ return [ 'pages_delete_confirm' => 'האם ברצונך למחוק דף זה?', 'pages_delete_draft_confirm' => 'האם ברצונך למחוק את טיוטת הדף הזה?', 'pages_editing_named' => 'עריכת דף :pageName', + 'pages_edit_draft_options' => 'Draft Options', 'pages_edit_save_draft' => 'שמור טיוטה', 'pages_edit_draft' => 'ערוך טיוטת דף', 'pages_editing_draft' => 'עריכת טיוטה', @@ -233,6 +234,7 @@ return [ ], 'pages_draft_discarded' => 'הסקיצה נמחקה, העורך עודכן עם תוכן הדף העכשוי', 'pages_specific' => 'דף ספציפי', + 'pages_is_template' => 'Page Template', // Editor Sidebar 'page_tags' => 'תגיות דף', @@ -241,9 +243,11 @@ return [ 'shelf_tags' => 'תגיות מדף', 'tag' => 'תגית', 'tags' => 'תגיות', + 'tag_name' => 'Tag Name', 'tag_value' => 'ערך התגית (אופציונאלי)', 'tags_explain' => "הכנס תגיות על מנת לסדר את התוכן שלך. \n ניתן לציין ערך לתגית על מנת לבצע סידור יסודי יותר", 'tags_add' => 'הוסף תגית נוספת', + 'tags_remove' => 'Remove this tag', 'attachments' => 'קבצים מצורפים', 'attachments_explain' => 'צרף קבצים או קישורים על מנת להציגם בדף שלך. צירופים אלו יהיו זמינים בתפריט הצדדי של הדף', 'attachments_explain_instant_save' => 'שינויים נשמרים באופן מיידי', @@ -269,6 +273,12 @@ return [ 'attachments_file_uploaded' => 'הקובץ עלה בהצלחה', 'attachments_file_updated' => 'הקובץ עודכן בהצלחה', 'attachments_link_attached' => 'הקישור צורף לדף בהצלחה', + 'templates' => 'Templates', + 'templates_set_as_template' => 'Page is a template', + 'templates_explain_set_as_template' => 'You can set this page as a template so its contents be utilized when creating other pages. Other users will be able to use this template if they have view permissions for this page.', + 'templates_replace_content' => 'Replace page content', + 'templates_append_content' => 'Append to page content', + 'templates_prepend_content' => 'Prepend to page content', // Profile View 'profile_user_for_x' => 'משתמש במערכת כ :time', diff --git a/resources/lang/he/errors.php b/resources/lang/he/errors.php index 0387947a4..9920f1b98 100644 --- a/resources/lang/he/errors.php +++ b/resources/lang/he/errors.php @@ -13,10 +13,16 @@ return [ 'email_already_confirmed' => 'המייל כבר אומת, אנא נסה להתחבר', 'email_confirmation_invalid' => 'מפתח האימות אינו תקין או שכבר נעשה בו שימוש, אנא נסה להרשם שנית', 'email_confirmation_expired' => 'מפתח האימות פג-תוקף, מייל אימות חדש נשלח שוב.', + 'email_confirmation_awaiting' => 'The email address for the account in use needs to be confirmed', 'ldap_fail_anonymous' => 'LDAP access failed using anonymous bind', 'ldap_fail_authed' => 'LDAP access failed using given dn & password details', 'ldap_extension_not_installed' => 'LDAP PHP extension not installed', 'ldap_cannot_connect' => 'Cannot connect to ldap server, Initial connection failed', + 'saml_already_logged_in' => 'Already logged in', + 'saml_user_not_registered' => 'The user :name is not registered and automatic registration is disabled', + 'saml_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system', + 'saml_invalid_response_id' => 'The request from the external authentication system is not recognised by a process started by this application. Navigating back after a login could cause this issue.', + 'saml_fail_authed' => 'Login using :system failed, system did not provide successful authorization', 'social_no_action_defined' => 'לא הוגדרה פעולה', 'social_login_bad_response' => "Error received during :socialAccount login: \n:error", 'social_account_in_use' => 'החשבון :socialAccount כבר בשימוש. אנא נסה להתחבר באמצעות אפשרות :socialAccount', @@ -27,6 +33,7 @@ return [ 'social_account_register_instructions' => 'אם אין ברשותך חשבון, תוכל להרשם באמצעות :socialAccount', 'social_driver_not_found' => 'Social driver not found', 'social_driver_not_configured' => 'הגדרות ה :socialAccount אינן מוגדרות כראוי', + 'invite_token_expired' => 'This invitation link has expired. You can instead try to reset your account password.', // System 'path_not_writable' => 'לא ניתן להעלות את :filePath אנא ודא שניתן לכתוב למיקום זה', @@ -76,9 +83,21 @@ return [ // Error pages '404_page_not_found' => 'דף לא קיים', 'sorry_page_not_found' => 'מצטערים, הדף שחיפשת אינו קיים', + 'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.', 'return_home' => 'בחזרה לדף הבית', 'error_occurred' => 'התרחשה שגיאה', 'app_down' => ':appName כרגע אינו זמין', 'back_soon' => 'מקווים שיחזור במהרה', + // API errors + 'api_no_authorization_found' => 'No authorization token found on the request', + 'api_bad_authorization_format' => 'An authorization token was found on the request but the format appeared incorrect', + 'api_user_token_not_found' => 'No matching API token was found for the provided authorization token', + 'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect', + 'api_user_no_api_permission' => 'The owner of the used API token does not have permission to make API calls', + 'api_user_token_expired' => 'The authorization token used has expired', + + // Settings & Maintenance + 'maintenance_test_email_failure' => 'Error thrown when sending a test email:', + ]; diff --git a/resources/lang/he/settings.php b/resources/lang/he/settings.php index 1b096e883..103f9398d 100755 --- a/resources/lang/he/settings.php +++ b/resources/lang/he/settings.php @@ -41,12 +41,22 @@ return [ 'app_disable_comments_toggle' => 'בטל תגובות', 'app_disable_comments_desc' => 'מבטל את התגובות לאורך כל היישום, תגובות קיימות לא יוצגו.', + // Color settings + 'content_colors' => 'Content Colors', + 'content_colors_desc' => 'Sets colors for all elements in the page organisation hierarchy. Choosing colors with a similar brightness to the default colors is recommended for readability.', + 'bookshelf_color' => 'Shelf Color', + 'book_color' => 'Book Color', + 'chapter_color' => 'Chapter Color', + 'page_color' => 'Page Color', + 'page_draft_color' => 'Page Draft Color', + // Registration Settings 'reg_settings' => 'הרשמה', 'reg_enable' => 'אפשר הרשמה', 'reg_enable_toggle' => 'אפשר להרשם', 'reg_enable_desc' => 'כאשר אפשר להרשם משתמשים יוכלו להכנס באופן עצמאי. בעת ההרשמה המשתמש יקבל הרשאה יחידה כברירת מחדל.', 'reg_default_role' => 'הרשאה כברירת מחדל', + 'reg_enable_external_warning' => 'The option above is ignored while external LDAP or SAML authentication is active. User accounts for non-existing members will be auto-created if authentication, against the external system in use, is successful.', 'reg_email_confirmation' => 'אימות כתובת אי-מייל', 'reg_email_confirmation_toggle' => 'יש לאמת את כתובת המייל', 'reg_confirm_email_desc' => 'אם מופעלת הגבלה לדומיין ספציפי אז אימות המייל לא יבוצע', @@ -63,6 +73,13 @@ return [ 'maint_image_cleanup_warning' => 'נמצאו כ :count תמונות אשר לא בשימוש האם ברצונך להמשיך?', 'maint_image_cleanup_success' => ':count תמונות שלא בשימוש נמחקו', 'maint_image_cleanup_nothing_found' => 'לא נמצאו תמונות אשר לא בשימוש, לא נמחקו קבצים כלל.', + 'maint_send_test_email' => 'Send a Test Email', + 'maint_send_test_email_desc' => 'This sends a test email to your email address specified in your profile.', + 'maint_send_test_email_run' => 'Send test email', + 'maint_send_test_email_success' => 'Email sent to :address', + 'maint_send_test_email_mail_subject' => 'Test Email', + 'maint_send_test_email_mail_greeting' => 'Email delivery seems to work!', + 'maint_send_test_email_mail_text' => 'Congratulations! As you received this email notification, your email settings seem to be configured properly.', // Role Settings 'roles' => 'תפקידים', @@ -85,6 +102,8 @@ return [ 'role_manage_roles' => 'ניהול תפקידים והרשאות תפקידים', 'role_manage_entity_permissions' => 'נהל הרשאות ספרים, פרקים ודפים', 'role_manage_own_entity_permissions' => 'נהל הרשאות על ספרים, פרקים ודפים בבעלותך', + 'role_manage_page_templates' => 'Manage page templates', + 'role_access_api' => 'Access system API', 'role_manage_settings' => 'ניהול הגדרות יישום', 'role_asset' => 'הרשאות משאבים', 'role_asset_desc' => 'הרשאות אלו שולטות בגישת ברירת המחדל למשאבים בתוך המערכת. הרשאות של ספרים, פרקים ודפים יגברו על הרשאות אלו.', @@ -109,6 +128,8 @@ return [ 'users_role_desc' => 'בחר אילו תפקידים ישויכו למשתמש זה. אם המשתמש משוייך למספר תפקידים, ההרשאות יהיו כלל ההרשאות של כל התפקידים', 'users_password' => 'סיסמא', 'users_password_desc' => 'הגדר סיסמא עבור גישה למערכת. על הסיסמא להיות באורך של 5 תווים לפחות', + 'users_send_invite_text' => 'You can choose to send this user an invitation email which allows them to set their own password otherwise you can set their password yourself.', + 'users_send_invite_option' => 'Send user invite email', 'users_external_auth_id' => 'זיהוי חיצוני - ID', 'users_external_auth_id_desc' => 'זיהוי זה יהיה בשימוש מול מערכת ה LDAP שלך', 'users_password_warning' => 'יש למלא רק אם ברצונך לשנות את הסיסמא.', @@ -131,4 +152,62 @@ return [ 'users_social_disconnect' => 'ניתוק חשבון', 'users_social_connected' => 'חשבון :socialAccount חובר בהצלחה לחשבון שלך', 'users_social_disconnected' => ':socialAccount נותק בהצלחה מהחשבון שלך', + 'users_api_tokens' => 'API Tokens', + 'users_api_tokens_none' => 'No API tokens have been created for this user', + 'users_api_tokens_create' => 'Create Token', + 'users_api_tokens_expires' => 'Expires', + 'users_api_tokens_docs' => 'API Documentation', + + // API Tokens + 'user_api_token_create' => 'Create API Token', + 'user_api_token_name' => 'Name', + 'user_api_token_name_desc' => 'Give your token a readable name as a future reminder of its intended purpose.', + 'user_api_token_expiry' => 'Expiry Date', + 'user_api_token_expiry_desc' => 'Set a date at which this token expires. After this date, requests made using this token will no longer work. Leaving this field blank will set an expiry 100 years into the future.', + 'user_api_token_create_secret_message' => 'Immediately after creating this token a "Token ID"" & "Token Secret" will be generated and displayed. The secret will only be shown a single time so be sure to copy the value to somewhere safe and secure before proceeding.', + 'user_api_token_create_success' => 'API token successfully created', + 'user_api_token_update_success' => 'API token successfully updated', + 'user_api_token' => 'API Token', + 'user_api_token_id' => 'Token ID', + 'user_api_token_id_desc' => 'This is a non-editable system generated identifier for this token which will need to be provided in API requests.', + 'user_api_token_secret' => 'Token Secret', + 'user_api_token_secret_desc' => 'This is a system generated secret for this token which will need to be provided in API requests. This will only be displayed this one time so copy this value to somewhere safe and secure.', + 'user_api_token_created' => 'Token Created :timeAgo', + 'user_api_token_updated' => 'Token Updated :timeAgo', + 'user_api_token_delete' => 'Delete Token', + 'user_api_token_delete_warning' => 'This will fully delete this API token with the name \':tokenName\' from the system.', + 'user_api_token_delete_confirm' => 'Are you sure you want to delete this API token?', + 'user_api_token_delete_success' => 'API token successfully deleted', + + //! If editing translations files directly please ignore this in all + //! languages apart from en. Content will be auto-copied from en. + //!//////////////////////////////// + 'language_select' => [ + 'en' => 'English', + 'ar' => 'العربية', + 'cs' => 'Česky', + 'da' => 'Dansk', + 'de' => 'Deutsch (Sie)', + 'de_informal' => 'Deutsch (Du)', + 'es' => 'Español', + 'es_AR' => 'Español Argentina', + 'fr' => 'Français', + 'hu' => 'Magyar', + 'it' => 'Italian', + 'ja' => '日本語', + 'ko' => '한국어', + 'nl' => 'Nederlands', + 'pl' => 'Polski', + 'pt_BR' => 'Português do Brasil', + 'ru' => 'Русский', + 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', + 'sv' => 'Svenska', + 'tr' => 'Türkçe', + 'uk' => 'Українська', + 'vi' => 'Tiếng Việt', + 'zh_CN' => '简体中文', + 'zh_TW' => '繁體中文', + ] + //!//////////////////////////////// ]; diff --git a/resources/lang/he/validation.php b/resources/lang/he/validation.php index 73f169d21..2797a9c21 100644 --- a/resources/lang/he/validation.php +++ b/resources/lang/he/validation.php @@ -8,43 +8,71 @@ return [ // Standard laravel validation lines - 'accepted' => 'שדה :attribute חייב להיות מסומן.', - 'active_url' => 'שדה :attribute הוא לא כתובת אתר תקנית.', - 'after' => 'שדה :attribute חייב להיות תאריך אחרי :date.', - 'alpha' => 'שדה :attribute יכול להכיל אותיות בלבד.', - 'alpha_dash' => 'שדה :attribute יכול להכיל אותיות, מספרים ומקפים בלבד.', - 'alpha_num' => 'שדה :attribute יכול להכיל אותיות ומספרים בלבד.', - 'array' => 'שדה :attribute חייב להיות מערך.', - 'before' => 'שדה :attribute חייב להיות תאריך לפני :date.', - 'between' => [ + 'accepted' => 'שדה :attribute חייב להיות מסומן.', + 'active_url' => 'שדה :attribute הוא לא כתובת אתר תקנית.', + 'after' => 'שדה :attribute חייב להיות תאריך אחרי :date.', + 'alpha' => 'שדה :attribute יכול להכיל אותיות בלבד.', + 'alpha_dash' => 'שדה :attribute יכול להכיל אותיות, מספרים ומקפים בלבד.', + 'alpha_num' => 'שדה :attribute יכול להכיל אותיות ומספרים בלבד.', + 'array' => 'שדה :attribute חייב להיות מערך.', + 'before' => 'שדה :attribute חייב להיות תאריך לפני :date.', + 'between' => [ 'numeric' => 'שדה :attribute חייב להיות בין :min ל-:max.', 'file' => 'שדה :attribute חייב להיות בין :min ל-:max קילובייטים.', 'string' => 'שדה :attribute חייב להיות בין :min ל-:max תווים.', 'array' => 'שדה :attribute חייב להיות בין :min ל-:max פריטים.', ], - 'boolean' => 'שדה :attribute חייב להיות אמת או שקר.', - 'confirmed' => 'שדה האישור של :attribute לא תואם.', - 'date' => 'שדה :attribute אינו תאריך תקני.', - 'date_format' => 'שדה :attribute לא תואם את הפורמט :format.', - 'different' => 'שדה :attribute ושדה :other חייבים להיות שונים.', - 'digits' => 'שדה :attribute חייב להיות בעל :digits ספרות.', - 'digits_between' => 'שדה :attribute חייב להיות בין :min ו-:max ספרות.', - 'email' => 'שדה :attribute חייב להיות כתובת אימייל תקנית.', - 'filled' => 'שדה :attribute הוא חובה.', - 'exists' => 'בחירת ה-:attribute אינה תקפה.', - 'image' => 'שדה :attribute חייב להיות תמונה.', + 'boolean' => 'שדה :attribute חייב להיות אמת או שקר.', + 'confirmed' => 'שדה האישור של :attribute לא תואם.', + 'date' => 'שדה :attribute אינו תאריך תקני.', + 'date_format' => 'שדה :attribute לא תואם את הפורמט :format.', + 'different' => 'שדה :attribute ושדה :other חייבים להיות שונים.', + 'digits' => 'שדה :attribute חייב להיות בעל :digits ספרות.', + 'digits_between' => 'שדה :attribute חייב להיות בין :min ו-:max ספרות.', + 'email' => 'שדה :attribute חייב להיות כתובת אימייל תקנית.', + 'ends_with' => 'The :attribute must end with one of the following: :values', + 'filled' => 'שדה :attribute הוא חובה.', + 'gt' => [ + 'numeric' => 'The :attribute must be greater than :value.', + 'file' => 'The :attribute must be greater than :value kilobytes.', + 'string' => 'The :attribute must be greater than :value characters.', + 'array' => 'The :attribute must have more than :value items.', + ], + 'gte' => [ + 'numeric' => 'The :attribute must be greater than or equal :value.', + 'file' => 'The :attribute must be greater than or equal :value kilobytes.', + 'string' => 'The :attribute must be greater than or equal :value characters.', + 'array' => 'The :attribute must have :value items or more.', + ], + 'exists' => 'בחירת ה-:attribute אינה תקפה.', + 'image' => 'שדה :attribute חייב להיות תמונה.', 'image_extension' => 'שדה :attribute חייב להיות מסוג תמונה נתמך', - 'in' => 'בחירת ה-:attribute אינה תקפה.', - 'integer' => 'שדה :attribute חייב להיות מספר שלם.', - 'ip' => 'שדה :attribute חייב להיות כתובת IP תקנית.', - 'max' => [ + 'in' => 'בחירת ה-:attribute אינה תקפה.', + 'integer' => 'שדה :attribute חייב להיות מספר שלם.', + 'ip' => 'שדה :attribute חייב להיות כתובת IP תקנית.', + 'ipv4' => 'The :attribute must be a valid IPv4 address.', + 'ipv6' => 'The :attribute must be a valid IPv6 address.', + 'json' => 'The :attribute must be a valid JSON string.', + 'lt' => [ + 'numeric' => 'The :attribute must be less than :value.', + 'file' => 'The :attribute must be less than :value kilobytes.', + 'string' => 'The :attribute must be less than :value characters.', + 'array' => 'The :attribute must have less than :value items.', + ], + 'lte' => [ + 'numeric' => 'The :attribute must be less than or equal :value.', + 'file' => 'The :attribute must be less than or equal :value kilobytes.', + 'string' => 'The :attribute must be less than or equal :value characters.', + 'array' => 'The :attribute must not have more than :value items.', + ], + 'max' => [ 'numeric' => 'שדה :attribute אינו יכול להיות גדול מ-:max.', 'file' => 'שדה :attribute לא יכול להיות גדול מ-:max קילובייטים.', 'string' => 'שדה :attribute לא יכול להיות גדול מ-:max characters.', 'array' => 'שדה :attribute לא יכול להכיל יותר מ-:max פריטים.', ], - 'mimes' => 'שדה :attribute צריך להיות קובץ מסוג: :values.', - 'min' => [ + 'mimes' => 'שדה :attribute צריך להיות קובץ מסוג: :values.', + 'min' => [ 'numeric' => 'שדה :attribute חייב להיות לפחות :min.', 'file' => 'שדה :attribute חייב להיות לפחות :min קילובייטים.', 'string' => 'שדה :attribute חייב להיות לפחות :min תווים.', @@ -52,6 +80,7 @@ return [ ], 'no_double_extension' => 'השדה :attribute חייב להיות בעל סיומת קובץ אחת בלבד.', 'not_in' => 'בחירת ה-:attribute אינה תקפה.', + 'not_regex' => 'The :attribute format is invalid.', 'numeric' => 'שדה :attribute חייב להיות מספר.', 'regex' => 'שדה :attribute בעל פורמט שאינו תקין.', 'required' => 'שדה :attribute הוא חובה.', @@ -67,11 +96,11 @@ return [ 'string' => 'שדה :attribute חייב להיות :size תווים.', 'array' => 'שדה :attribute חייב להכיל :size פריטים.', ], - 'string' => 'שדה :attribute חייב להיות מחרוזת.', - 'timezone' => 'שדה :attribute חייב להיות איזור תקני.', - 'unique' => 'שדה :attribute כבר תפוס.', - 'url' => 'שדה :attribute בעל פורמט שאינו תקין.', - 'uploaded' => 'שדה :attribute ארעה שגיאה בעת ההעלאה.', + 'string' => 'שדה :attribute חייב להיות מחרוזת.', + 'timezone' => 'שדה :attribute חייב להיות איזור תקני.', + 'unique' => 'שדה :attribute כבר תפוס.', + 'url' => 'שדה :attribute בעל פורמט שאינו תקין.', + 'uploaded' => 'שדה :attribute ארעה שגיאה בעת ההעלאה.', // Custom validation lines 'custom' => [ diff --git a/resources/lang/hu/settings.php b/resources/lang/hu/settings.php index 70dae98ff..8a87db85a 100644 --- a/resources/lang/hu/settings.php +++ b/resources/lang/hu/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/it/errors.php b/resources/lang/it/errors.php index cb49355a9..ca605cde0 100755 --- a/resources/lang/it/errors.php +++ b/resources/lang/it/errors.php @@ -13,7 +13,7 @@ return [ 'email_already_confirmed' => 'La mail è già stata confermata, esegui il login.', 'email_confirmation_invalid' => 'Questo token di conferma non è valido o già stato utilizzato, registrati nuovamente.', 'email_confirmation_expired' => 'Il token di conferma è scaduto, è stata inviata una nuova mail di conferma.', - 'email_confirmation_awaiting' => 'The email address for the account in use needs to be confirmed', + 'email_confirmation_awaiting' => 'L\'indirizzo email per l\'account in uso deve essere confermato', 'ldap_fail_anonymous' => 'Accesso LDAP fallito usando bind anonimo', 'ldap_fail_authed' => 'Accesso LDAP fallito usando il dn e la password inseriti', 'ldap_extension_not_installed' => 'L\'estensione PHP LDAP non è installata', @@ -83,7 +83,7 @@ return [ // Error pages '404_page_not_found' => 'Pagina Non Trovata', 'sorry_page_not_found' => 'La pagina che stavi cercando non è stata trovata.', - 'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.', + 'sorry_page_not_found_permission_warning' => 'Se pensi che questa pagina possa esistere, potresti non avere i permessi per visualizzarla.', 'return_home' => 'Ritorna alla home', 'error_occurred' => 'C\'è Stato un errore', 'app_down' => ':appName è offline', @@ -91,10 +91,10 @@ return [ // API errors 'api_no_authorization_found' => 'No authorization token found on the request', - 'api_bad_authorization_format' => 'An authorization token was found on the request but the format appeared incorrect', + 'api_bad_authorization_format' => 'Un token di autorizzazione è stato trovato nella richiesta, ma il formato sembra non corretto', 'api_user_token_not_found' => 'No matching API token was found for the provided authorization token', 'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect', - 'api_user_no_api_permission' => 'The owner of the used API token does not have permission to make API calls', + 'api_user_no_api_permission' => 'Il proprietario del token API utilizzato non ha il permesso di effettuare chiamate API', 'api_user_token_expired' => 'The authorization token used has expired', // Settings & Maintenance diff --git a/resources/lang/it/settings.php b/resources/lang/it/settings.php index 31babe171..d4fb0b9c6 100755 --- a/resources/lang/it/settings.php +++ b/resources/lang/it/settings.php @@ -160,9 +160,9 @@ return [ // API Tokens 'user_api_token_create' => 'Create API Token', - 'user_api_token_name' => 'Name', + 'user_api_token_name' => 'Nome', 'user_api_token_name_desc' => 'Give your token a readable name as a future reminder of its intended purpose.', - 'user_api_token_expiry' => 'Expiry Date', + 'user_api_token_expiry' => 'Data di scadenza', 'user_api_token_expiry_desc' => 'Set a date at which this token expires. After this date, requests made using this token will no longer work. Leaving this field blank will set an expiry 100 years into the future.', 'user_api_token_create_secret_message' => 'Immediately after creating this token a "Token ID"" & "Token Secret" will be generated and displayed. The secret will only be shown a single time so be sure to copy the value to somewhere safe and secure before proceeding.', 'user_api_token_create_success' => 'API token successfully created', @@ -186,7 +186,7 @@ return [ 'en' => 'English', 'ar' => 'العربية', 'cs' => 'Česky', - 'da' => 'Dansk', + 'da' => 'Danese', 'de' => 'Deutsch (Sie)', 'de_informal' => 'Deutsch (Du)', 'es' => 'Español', @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Sloveno', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/ja/settings.php b/resources/lang/ja/settings.php index 74f4a99ec..3da916877 100644 --- a/resources/lang/ja/settings.php +++ b/resources/lang/ja/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/ko/settings.php b/resources/lang/ko/settings.php index 262671dfe..bd23e380f 100755 --- a/resources/lang/ko/settings.php +++ b/resources/lang/ko/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/nl/settings.php b/resources/lang/nl/settings.php index 7cd679765..069ee65f8 100644 --- a/resources/lang/nl/settings.php +++ b/resources/lang/nl/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/pl/settings.php b/resources/lang/pl/settings.php index 14bf8279f..97f4222d6 100644 --- a/resources/lang/pl/settings.php +++ b/resources/lang/pl/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/pt/settings.php b/resources/lang/pt/settings.php index 46ad7b578..35bb09cd4 100644 --- a/resources/lang/pt/settings.php +++ b/resources/lang/pt/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/pt_BR/settings.php b/resources/lang/pt_BR/settings.php index 375400727..bc78f8328 100644 --- a/resources/lang/pt_BR/settings.php +++ b/resources/lang/pt_BR/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/ru/auth.php b/resources/lang/ru/auth.php index ff651a145..369da7aa3 100644 --- a/resources/lang/ru/auth.php +++ b/resources/lang/ru/auth.php @@ -74,4 +74,4 @@ return [ 'user_invite_page_text' => 'Завершите настройку аккаунта, установите пароль для дальнейшего входа в :appName.', 'user_invite_page_confirm_button' => 'Подтвердите пароль', 'user_invite_success' => 'Пароль установлен, теперь у вас есть доступ к :appName!' -]; +]; \ No newline at end of file diff --git a/resources/lang/ru/entities.php b/resources/lang/ru/entities.php index ceb6bbc94..fc180061a 100644 --- a/resources/lang/ru/entities.php +++ b/resources/lang/ru/entities.php @@ -311,4 +311,4 @@ return [ 'revision_restore_confirm' => 'Вы уверены, что хотите восстановить эту версию? Текущее содержимое страницы будет заменено.', 'revision_delete_success' => 'Версия удалена', 'revision_cannot_delete_latest' => 'Нельзя удалить последнюю версию.' -]; +]; \ No newline at end of file diff --git a/resources/lang/ru/errors.php b/resources/lang/ru/errors.php index 3f6906801..0cc4a72b1 100644 --- a/resources/lang/ru/errors.php +++ b/resources/lang/ru/errors.php @@ -83,7 +83,7 @@ return [ // Error pages '404_page_not_found' => 'Страница не найдена', 'sorry_page_not_found' => 'Извините, страница, которую вы искали, не найдена.', - 'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.', + 'sorry_page_not_found_permission_warning' => 'Если вы ожидали что страница существует, возможно у вас нет прав для её просмотра.', 'return_home' => 'вернуться на главную страницу', 'error_occurred' => 'Произошла ошибка', 'app_down' => ':appName в данный момент не доступно', diff --git a/resources/lang/ru/settings.php b/resources/lang/ru/settings.php index a3fcde7ff..8eeb3bca1 100755 --- a/resources/lang/ru/settings.php +++ b/resources/lang/ru/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/sk/settings.php b/resources/lang/sk/settings.php index 4fe88a815..ce6821890 100644 --- a/resources/lang/sk/settings.php +++ b/resources/lang/sk/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/sl/entities.php b/resources/lang/sl/entities.php index bd96274e4..ff1382159 100644 --- a/resources/lang/sl/entities.php +++ b/resources/lang/sl/entities.php @@ -168,56 +168,56 @@ return [ 'pages_attachments' => 'Priloge', 'pages_navigation' => 'Navigacija po strani', 'pages_delete' => 'Izbriši stran', - 'pages_delete_named' => 'Delete Page :pageName', - 'pages_delete_draft_named' => 'Delete Draft Page :pageName', - 'pages_delete_draft' => 'Delete Draft Page', - 'pages_delete_success' => 'Page deleted', - 'pages_delete_draft_success' => 'Draft page deleted', - 'pages_delete_confirm' => 'Are you sure you want to delete this page?', - 'pages_delete_draft_confirm' => 'Are you sure you want to delete this draft page?', - 'pages_editing_named' => 'Editing Page :pageName', - 'pages_edit_draft_options' => 'Draft Options', - 'pages_edit_save_draft' => 'Save Draft', - 'pages_edit_draft' => 'Edit Page Draft', - 'pages_editing_draft' => 'Editing Draft', - 'pages_editing_page' => 'Editing Page', - 'pages_edit_draft_save_at' => 'Draft saved at ', - 'pages_edit_delete_draft' => 'Delete Draft', - 'pages_edit_discard_draft' => 'Discard Draft', - 'pages_edit_set_changelog' => 'Set Changelog', - 'pages_edit_enter_changelog_desc' => 'Enter a brief description of the changes you\'ve made', - 'pages_edit_enter_changelog' => 'Enter Changelog', - 'pages_save' => 'Save Page', - 'pages_title' => 'Page Title', - 'pages_name' => 'Page Name', - 'pages_md_editor' => 'Editor', - 'pages_md_preview' => 'Preview', - 'pages_md_insert_image' => 'Insert Image', - 'pages_md_insert_link' => 'Insert Entity Link', - 'pages_md_insert_drawing' => 'Insert Drawing', - 'pages_not_in_chapter' => 'Page is not in a chapter', - 'pages_move' => 'Move Page', - 'pages_move_success' => 'Page moved to ":parentName"', - 'pages_copy' => 'Copy Page', - 'pages_copy_desination' => 'Copy Destination', - 'pages_copy_success' => 'Page successfully copied', - 'pages_permissions' => 'Page Permissions', - 'pages_permissions_success' => 'Page permissions updated', - 'pages_revision' => 'Revision', - 'pages_revisions' => 'Page Revisions', - 'pages_revisions_named' => 'Page Revisions for :pageName', - 'pages_revision_named' => 'Page Revision for :pageName', - 'pages_revisions_created_by' => 'Created By', - 'pages_revisions_date' => 'Revision Date', + 'pages_delete_named' => 'Izbriši stran :pageName', + 'pages_delete_draft_named' => 'Izbriši osnutek strani :pageName', + 'pages_delete_draft' => 'Izbriši osnutek strani', + 'pages_delete_success' => 'Stran izbirsana', + 'pages_delete_draft_success' => 'Osnutek strani izbrisan', + 'pages_delete_confirm' => 'Ste prepričani, da želite izbrisati to stran?', + 'pages_delete_draft_confirm' => 'Ali ste prepričani, da želite izbrisati ta osnutek?', + 'pages_editing_named' => 'Urejanje strani :pageName', + 'pages_edit_draft_options' => 'Možnosti osnutka', + 'pages_edit_save_draft' => 'Shrani osnutek', + 'pages_edit_draft' => 'Uredi osnutek strani', + 'pages_editing_draft' => 'Urejanje osnutka', + 'pages_editing_page' => 'Urejanje strani', + 'pages_edit_draft_save_at' => 'Osnutek shranjen ob ', + 'pages_edit_delete_draft' => 'Izbriši osnutek', + 'pages_edit_discard_draft' => 'Zavrzi osnutek', + 'pages_edit_set_changelog' => 'Nastavi zgodovino sprememb', + 'pages_edit_enter_changelog_desc' => 'Vnesite kratek opis sprememb, ki ste jih naredili', + 'pages_edit_enter_changelog' => 'Vnesite zgodovino sprememb', + 'pages_save' => 'Shrani stran', + 'pages_title' => 'Naslov strani', + 'pages_name' => 'Ime strani', + 'pages_md_editor' => 'Urejevalnik', + 'pages_md_preview' => 'Predogled', + 'pages_md_insert_image' => 'Vstavi sliko', + 'pages_md_insert_link' => 'Vnesi povezavo entitete', + 'pages_md_insert_drawing' => 'Vstavi risbo', + 'pages_not_in_chapter' => 'Stran ni v poglavju', + 'pages_move' => 'Premakni stran', + 'pages_move_success' => 'Stran premaknjena v ":parentName"', + 'pages_copy' => 'Kopiraj stran', + 'pages_copy_desination' => 'Destinacija kopije', + 'pages_copy_success' => 'Stran uspešno kopirana', + 'pages_permissions' => 'Dovoljenja strani', + 'pages_permissions_success' => 'Posodobljena dovoljenja strani', + 'pages_revision' => 'Revizija', + 'pages_revisions' => 'Pregled strani', + 'pages_revisions_named' => 'Pregledi strani za :pageName', + 'pages_revision_named' => 'Pregled strani za :pageName', + 'pages_revisions_created_by' => 'Ustvaril', + 'pages_revisions_date' => 'Datum revizije', 'pages_revisions_number' => '#', - 'pages_revisions_numbered' => 'Revision #:id', - 'pages_revisions_numbered_changes' => 'Revision #:id Changes', - 'pages_revisions_changelog' => 'Changelog', - 'pages_revisions_changes' => 'Changes', - 'pages_revisions_current' => 'Current Version', - 'pages_revisions_preview' => 'Preview', - 'pages_revisions_restore' => 'Restore', - 'pages_revisions_none' => 'This page has no revisions', + 'pages_revisions_numbered' => 'Revizija #:id', + 'pages_revisions_numbered_changes' => 'Revizija #:id Changes', + 'pages_revisions_changelog' => 'Dnevnik sprememb', + 'pages_revisions_changes' => 'Spremembe', + 'pages_revisions_current' => 'Trenutna različica', + 'pages_revisions_preview' => 'Predogled', + 'pages_revisions_restore' => 'Obnovi', + 'pages_revisions_none' => 'Ta stran nima revizije', 'pages_copy_link' => 'Kopiraj povezavo', 'pages_edit_content_link' => 'Uredi vsebino', 'pages_permissions_active' => 'Aktivna dovoljenja strani', @@ -272,43 +272,43 @@ return [ 'attachments_deleted' => 'Priloga izbirsana', 'attachments_file_uploaded' => 'Datoteka uspešno naložena', 'attachments_file_updated' => 'Datoteka uspešno posodobljena', - 'attachments_link_attached' => 'Link successfully attached to page', - 'templates' => 'Templates', - 'templates_set_as_template' => 'Page is a template', - 'templates_explain_set_as_template' => 'You can set this page as a template so its contents be utilized when creating other pages. Other users will be able to use this template if they have view permissions for this page.', - 'templates_replace_content' => 'Replace page content', - 'templates_append_content' => 'Append to page content', - 'templates_prepend_content' => 'Prepend to page content', + 'attachments_link_attached' => 'Povezava uspešno dodana na stran', + 'templates' => 'Predloge', + 'templates_set_as_template' => 'Stran je predloga', + 'templates_explain_set_as_template' => 'To stran lahko nastavite kot predlogo tako bo njena vsebina uporabljena pri izdelavi drugih strani. Ostali uporabniki bodo lahko uporabljali to predlogo, če imajo dovoljenja za to stran.', + 'templates_replace_content' => 'Zamenjaj vsebino strani', + 'templates_append_content' => 'Dodajte vsebini strani', + 'templates_prepend_content' => 'Dodaj k vsebini strani', // Profile View - 'profile_user_for_x' => 'User for :time', - 'profile_created_content' => 'Created Content', - 'profile_not_created_pages' => ':userName has not created any pages', - 'profile_not_created_chapters' => ':userName has not created any chapters', - 'profile_not_created_books' => ':userName has not created any books', - 'profile_not_created_shelves' => ':userName has not created any shelves', + 'profile_user_for_x' => 'Uporabnik že :time', + 'profile_created_content' => 'Ustvarjena vsebina', + 'profile_not_created_pages' => ':userName ni izdelal nobene strani', + 'profile_not_created_chapters' => ':userName ni izdelal nobenega poglavja', + 'profile_not_created_books' => ':userName ni izdelal nobene knjige', + 'profile_not_created_shelves' => ':userName ni izdelal nobene knjižne police', // Comments - 'comment' => 'Comment', - 'comments' => 'Comments', - 'comment_add' => 'Add Comment', - 'comment_placeholder' => 'Leave a comment here', - 'comment_count' => '{0} No Comments|{1} 1 Comment|[2,*] :count Comments', - 'comment_save' => 'Save Comment', - 'comment_saving' => 'Saving comment...', - 'comment_deleting' => 'Deleting comment...', - 'comment_new' => 'New Comment', - 'comment_created' => 'commented :createDiff', - 'comment_updated' => 'Updated :updateDiff by :username', - 'comment_deleted_success' => 'Comment deleted', - 'comment_created_success' => 'Comment added', - 'comment_updated_success' => 'Comment updated', - 'comment_delete_confirm' => 'Are you sure you want to delete this comment?', - 'comment_in_reply_to' => 'In reply to :commentId', + 'comment' => 'Komentar', + 'comments' => 'Komentarji', + 'comment_add' => 'Dodaj komentar', + 'comment_placeholder' => 'Dodaj komentar', + 'comment_count' => '{0} Ni komentarjev|{1} 1 Komentar|[2,*] :count Komentarji', + 'comment_save' => 'Shrani komentar', + 'comment_saving' => 'Shranjujem komentar...', + 'comment_deleting' => 'Brišem komentar...', + 'comment_new' => 'Nov kometar', + 'comment_created' => 'komentirano :createDiff', + 'comment_updated' => 'Posodobljeno :updateDiff od :username', + 'comment_deleted_success' => 'Komentar je izbrisan', + 'comment_created_success' => 'Komentar dodan', + 'comment_updated_success' => 'Komentar posodobljen', + 'comment_delete_confirm' => 'Ste prepričani, da želite izbrisati ta komentar?', + 'comment_in_reply_to' => 'Odgovor na :commentId', // Revision - 'revision_delete_confirm' => 'Are you sure you want to delete this revision?', - 'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.', - 'revision_delete_success' => 'Revision deleted', - 'revision_cannot_delete_latest' => 'Cannot delete the latest revision.' + 'revision_delete_confirm' => 'Ali ste prepričani, da želite izbrisati to revizijo?', + 'revision_restore_confirm' => 'Ali ste prepričani da želite obnoviti to revizijo? Vsebina trenutne strani bo zamenjana.', + 'revision_delete_success' => 'Revizija izbrisana', + 'revision_cannot_delete_latest' => 'Ne morem izbrisati zadnje revizije.' ]; \ No newline at end of file diff --git a/resources/lang/sl/errors.php b/resources/lang/sl/errors.php index 06a5285f5..bf1564eef 100644 --- a/resources/lang/sl/errors.php +++ b/resources/lang/sl/errors.php @@ -5,99 +5,99 @@ return [ // Permissions - 'permission' => 'You do not have permission to access the requested page.', - 'permissionJson' => 'You do not have permission to perform the requested action.', + 'permission' => 'Nimate pravic za dostop do želene strani.', + 'permissionJson' => 'Nimate dovoljenja za izvedbo zahtevanega dejanja.', // Auth - 'error_user_exists_different_creds' => 'A user with the email :email already exists but with different credentials.', - 'email_already_confirmed' => 'Email has already been confirmed, Try logging in.', - 'email_confirmation_invalid' => 'This confirmation token is not valid or has already been used, Please try registering again.', - 'email_confirmation_expired' => 'The confirmation token has expired, A new confirmation email has been sent.', - 'email_confirmation_awaiting' => 'The email address for the account in use needs to be confirmed', - 'ldap_fail_anonymous' => 'LDAP access failed using anonymous bind', - 'ldap_fail_authed' => 'LDAP access failed using given dn & password details', - 'ldap_extension_not_installed' => 'LDAP PHP extension not installed', - 'ldap_cannot_connect' => 'Cannot connect to ldap server, Initial connection failed', - 'saml_already_logged_in' => 'Already logged in', - 'saml_user_not_registered' => 'The user :name is not registered and automatic registration is disabled', - 'saml_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system', - 'saml_invalid_response_id' => 'The request from the external authentication system is not recognised by a process started by this application. Navigating back after a login could cause this issue.', - 'saml_fail_authed' => 'Login using :system failed, system did not provide successful authorization', - 'social_no_action_defined' => 'No action defined', - 'social_login_bad_response' => "Error received during :socialAccount login: \n:error", - 'social_account_in_use' => 'This :socialAccount account is already in use, Try logging in via the :socialAccount option.', - 'social_account_email_in_use' => 'The email :email is already in use. If you already have an account you can connect your :socialAccount account from your profile settings.', - 'social_account_existing' => 'This :socialAccount is already attached to your profile.', - 'social_account_already_used_existing' => 'This :socialAccount account is already used by another user.', - 'social_account_not_used' => 'This :socialAccount account is not linked to any users. Please attach it in your profile settings. ', - 'social_account_register_instructions' => 'If you do not yet have an account, You can register an account using the :socialAccount option.', - 'social_driver_not_found' => 'Social driver not found', - 'social_driver_not_configured' => 'Your :socialAccount social settings are not configured correctly.', - 'invite_token_expired' => 'This invitation link has expired. You can instead try to reset your account password.', + 'error_user_exists_different_creds' => 'Uporabnik z e-pošto :email že obstaja, vendar z drugačnimi poverilnicami.', + 'email_already_confirmed' => 'E-naslov je že bil potrjen, poskusite se prijaviti.', + 'email_confirmation_invalid' => 'Ta potrditveni žeton ni veljaven ali je že bil uporabljen. Poizkusite znova.', + 'email_confirmation_expired' => 'Potrditveni žeton je pretečen. Nova potrditvena e-pošta je bila poslana.', + 'email_confirmation_awaiting' => 'Potrebno je potrditi e-naslov', + 'ldap_fail_anonymous' => 'Dostop do LDAP ni uspel z anonimno povezavo', + 'ldap_fail_authed' => 'Neuspešen LDAP dostop z danimi podrobnostimi dn & gesla', + 'ldap_extension_not_installed' => 'PHP razširitev za LDAP ni nameščen', + 'ldap_cannot_connect' => 'Ne morem se povezati na LDAP strežnik, neuspešna začetna povezava', + 'saml_already_logged_in' => 'Že prijavljen', + 'saml_user_not_registered' => 'Uporabniško ime :name ni registrirano in avtomatska registracija je onemogočena', + 'saml_no_email_address' => 'Nisem našel e-naslova za tega uporabnika v podatkih iz zunanjega sistema za preverjanje pristnosti', + 'saml_invalid_response_id' => 'Zahteva iz zunanjega sistema za preverjanje pristnosti ni prepoznana s strani procesa zagnanega s strani te aplikacije. Pomik nazaj po prijavi je lahko povzročil te težave.', + 'saml_fail_authed' => 'Prijava z uporabo :system ni uspela, sistem ni zagotovil uspešne avtorizacije', + 'social_no_action_defined' => 'Akcija ni določena', + 'social_login_bad_response' => "Napaka pri :socialAccount prijavi:\n:error", + 'social_account_in_use' => 'Ta :socialAccount je že v uporabi. Poskusite se prijaviti z :socialAccount možnostjo.', + 'social_account_email_in_use' => 'Ta e-naslov :email je že v uporabi. Če že imate račun lahko povežete vaš :socialAccount v vaših nastavitvah profila.', + 'social_account_existing' => 'Ta :socialAccount je že dodan vašemu profilu.', + 'social_account_already_used_existing' => 'Ta :socialAccount je v uporabi s strani drugega uporabnika.', + 'social_account_not_used' => 'Ta :socialAccount ni povezan z nobenim uporabnikom. Prosimo povežite ga v vaših nastavitvah profila. ', + 'social_account_register_instructions' => 'Če še nimate računa, se lahko registrirate z uporabo :socialAccount.', + 'social_driver_not_found' => 'Socialni vtičnik ni najden', + 'social_driver_not_configured' => 'Vaše nastavitve :socialAccount niso pravilo nastavljene.', + 'invite_token_expired' => 'Ta link je pretečen. Namesto tega lahko ponastavite vaše geslo računa.', // System - 'path_not_writable' => 'File path :filePath could not be uploaded to. Ensure it is writable to the server.', - 'cannot_get_image_from_url' => 'Cannot get image from :url', - 'cannot_create_thumbs' => 'The server cannot create thumbnails. Please check you have the GD PHP extension installed.', - 'server_upload_limit' => 'The server does not allow uploads of this size. Please try a smaller file size.', - 'uploaded' => 'The server does not allow uploads of this size. Please try a smaller file size.', - 'image_upload_error' => 'An error occurred uploading the image', - 'image_upload_type_error' => 'The image type being uploaded is invalid', - 'file_upload_timeout' => 'The file upload has timed out.', + 'path_not_writable' => 'Poti :filePath ni bilo mogoče naložiti. Prepričajte se da je zapisljiva na strežnik.', + 'cannot_get_image_from_url' => 'Ne morem pridobiti slike z :url', + 'cannot_create_thumbs' => 'Strežnik ne more izdelati sličice. Prosimo preverite če imate GD PHP razširitev nameščeno.', + 'server_upload_limit' => 'Strežnik ne dovoli nalaganj take velikosti. Prosimo poskusite manjšo velikost datoteke.', + 'uploaded' => 'Strežnik ne dovoli nalaganj take velikosti. Prosimo poskusite manjšo velikost datoteke.', + 'image_upload_error' => 'Prišlo je do napake med nalaganjem slike', + 'image_upload_type_error' => 'Napačen tip (format) slike', + 'file_upload_timeout' => 'Čas nalaganjanja datoteke je potekel.', // Attachments - 'attachment_page_mismatch' => 'Page mismatch during attachment update', - 'attachment_not_found' => 'Attachment not found', + 'attachment_page_mismatch' => 'Neskladje strani med posodobitvijo priloge', + 'attachment_not_found' => 'Priloga ni najdena', // Pages - 'page_draft_autosave_fail' => 'Failed to save draft. Ensure you have internet connection before saving this page', - 'page_custom_home_deletion' => 'Cannot delete a page while it is set as a homepage', + 'page_draft_autosave_fail' => 'Osnutka ni bilo mogoče shraniti. Pred shranjevanjem te strani se prepričajte, da imate internetno povezavo', + 'page_custom_home_deletion' => 'Ne morem izbrisati strani dokler je nastavljena kot domača stran', // Entities - 'entity_not_found' => 'Entity not found', - 'bookshelf_not_found' => 'Bookshelf not found', - 'book_not_found' => 'Book not found', - 'page_not_found' => 'Page not found', - 'chapter_not_found' => 'Chapter not found', - 'selected_book_not_found' => 'The selected book was not found', - 'selected_book_chapter_not_found' => 'The selected Book or Chapter was not found', - 'guests_cannot_save_drafts' => 'Guests cannot save drafts', + 'entity_not_found' => 'Entiteta ni najdena', + 'bookshelf_not_found' => 'Knjižna polica ni najdena', + 'book_not_found' => 'Knjiga ni najdena', + 'page_not_found' => 'Stran ni najdena', + 'chapter_not_found' => 'Poglavje ni najdeno', + 'selected_book_not_found' => 'Izbrana knjiga ni najdena', + 'selected_book_chapter_not_found' => 'Izbrana knjiga ali poglavje ni najdeno', + 'guests_cannot_save_drafts' => 'Gosti ne morejo shranjevati osnutkov', // Users - 'users_cannot_delete_only_admin' => 'You cannot delete the only admin', - 'users_cannot_delete_guest' => 'You cannot delete the guest user', + 'users_cannot_delete_only_admin' => 'Ne morete odstraniti edinega administratorja', + 'users_cannot_delete_guest' => 'Ne morete odstraniti uporabnika gost', // Roles - 'role_cannot_be_edited' => 'This role cannot be edited', - 'role_system_cannot_be_deleted' => 'This role is a system role and cannot be deleted', - 'role_registration_default_cannot_delete' => 'This role cannot be deleted while set as the default registration role', - 'role_cannot_remove_only_admin' => 'This user is the only user assigned to the administrator role. Assign the administrator role to another user before attempting to remove it here.', + 'role_cannot_be_edited' => 'Te vloge mi možno urejati', + 'role_system_cannot_be_deleted' => 'Ta vloga je sistemska in je ni možno brisati', + 'role_registration_default_cannot_delete' => 'Te vloge ni možno brisati dokler je nastavljena kot privzeta', + 'role_cannot_remove_only_admin' => 'Ta uporabnik je edini administrator. Dodelite vlogo administratorja drugemu uporabniku preden ga poskusite brisati.', // Comments - 'comment_list' => 'An error occurred while fetching the comments.', - 'cannot_add_comment_to_draft' => 'You cannot add comments to a draft.', - 'comment_add' => 'An error occurred while adding / updating the comment.', - 'comment_delete' => 'An error occurred while deleting the comment.', - 'empty_comment' => 'Cannot add an empty comment.', + 'comment_list' => 'Napaka se je pojavila pri pridobivanju komentarjev.', + 'cannot_add_comment_to_draft' => 'Ni mogoče dodajanje komentarjev v osnutek.', + 'comment_add' => 'Napaka se je pojavila pri dodajanju / posodobitev komentarjev.', + 'comment_delete' => 'Napaka se je pojavila pri brisanju komentarja.', + 'empty_comment' => 'Praznega komentarja ne morete objaviti.', // Error pages - '404_page_not_found' => 'Page Not Found', - 'sorry_page_not_found' => 'Sorry, The page you were looking for could not be found.', - 'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.', - 'return_home' => 'Return to home', - 'error_occurred' => 'An Error Occurred', - 'app_down' => ':appName is down right now', - 'back_soon' => 'It will be back up soon.', + '404_page_not_found' => 'Strani ni mogoče najti', + 'sorry_page_not_found' => 'Oprostite, strani ki jo iščete ni mogoče najti.', + 'sorry_page_not_found_permission_warning' => 'Če pričakujete, da ta stran obstaja, mogoče nimate pravic, da jo vidite.', + 'return_home' => 'Vrni se domov', + 'error_occurred' => 'Prišlo je do napake', + 'app_down' => ':appName trenutno ni dosegljiva', + 'back_soon' => 'Kmalu bo ponovno dosegljiva.', // API errors - 'api_no_authorization_found' => 'No authorization token found on the request', - 'api_bad_authorization_format' => 'An authorization token was found on the request but the format appeared incorrect', - 'api_user_token_not_found' => 'No matching API token was found for the provided authorization token', - 'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect', - 'api_user_no_api_permission' => 'The owner of the used API token does not have permission to make API calls', - 'api_user_token_expired' => 'The authorization token used has expired', + 'api_no_authorization_found' => 'Avtorizacija ni bila najdena', + 'api_bad_authorization_format' => 'Avtorizacija je bila najdena, vendar je v napačni obliki', + 'api_user_token_not_found' => 'Za dano avtorizacijo ni bil najden noben ustrezen API', + 'api_incorrect_token_secret' => 'Skrivnost, ki je bila dana za uporabljeni žeton API, je napačna', + 'api_user_no_api_permission' => 'Lastnik API nima pravic za klicanje API', + 'api_user_token_expired' => 'Avtorizacijski žeton je pretečen', // Settings & Maintenance - 'maintenance_test_email_failure' => 'Error thrown when sending a test email:', + 'maintenance_test_email_failure' => 'Napaka se je pojavila pri pošiljanju testne e-pošte:', ]; diff --git a/resources/lang/sl/pagination.php b/resources/lang/sl/pagination.php index 85bd12fc3..b7df08291 100644 --- a/resources/lang/sl/pagination.php +++ b/resources/lang/sl/pagination.php @@ -6,7 +6,7 @@ */ return [ - 'previous' => '« Previous', - 'next' => 'Next »', + 'previous' => '« Prejšnje', + 'next' => 'Naslednje »', ]; diff --git a/resources/lang/sl/passwords.php b/resources/lang/sl/passwords.php index f41ca7868..12e52ef28 100644 --- a/resources/lang/sl/passwords.php +++ b/resources/lang/sl/passwords.php @@ -6,10 +6,10 @@ */ return [ - 'password' => 'Passwords must be at least eight characters and match the confirmation.', - 'user' => "We can't find a user with that e-mail address.", - 'token' => 'This password reset token is invalid.', - 'sent' => 'We have e-mailed your password reset link!', - 'reset' => 'Your password has been reset!', + 'password' => 'Gesla morajo biti najmanj osem znakov in se morajo ujemati s potrditvijo.', + 'user' => "Ne moremo najti uporabnika s tem e-poštnim naslovom.", + 'token' => 'Žeton za ponastavitev gesla ni veljaven.', + 'sent' => 'Poslali smo vam povezavo za ponastavitev gesla!', + 'reset' => 'Vaše geslo je bilo ponastavljeno!', ]; diff --git a/resources/lang/sl/settings.php b/resources/lang/sl/settings.php index 46ad7b578..09e687c8c 100644 --- a/resources/lang/sl/settings.php +++ b/resources/lang/sl/settings.php @@ -7,177 +7,181 @@ return [ // Common Messages - 'settings' => 'Settings', - 'settings_save' => 'Save Settings', - 'settings_save_success' => 'Settings saved', + 'settings' => 'Nastavitve', + 'settings_save' => 'Shrani nastavitve', + 'settings_save_success' => 'Nastavitve, shranjene', // App Settings - 'app_customization' => 'Customization', - 'app_features_security' => 'Features & Security', - 'app_name' => 'Application Name', - 'app_name_desc' => 'This name is shown in the header and in any system-sent emails.', - 'app_name_header' => 'Show name in header', - 'app_public_access' => 'Public Access', - 'app_public_access_desc' => 'Enabling this option will allow visitors, that are not logged-in, to access content in your BookStack instance.', - 'app_public_access_desc_guest' => 'Access for public visitors can be controlled through the "Guest" user.', - 'app_public_access_toggle' => 'Allow public access', - 'app_public_viewing' => 'Allow public viewing?', - 'app_secure_images' => 'Higher Security Image Uploads', - 'app_secure_images_toggle' => 'Enable higher security image uploads', - 'app_secure_images_desc' => 'For performance reasons, all images are public. This option adds a random, hard-to-guess string in front of image urls. Ensure directory indexes are not enabled to prevent easy access.', - 'app_editor' => 'Page Editor', - 'app_editor_desc' => 'Select which editor will be used by all users to edit pages.', - 'app_custom_html' => 'Custom HTML Head Content', - 'app_custom_html_desc' => 'Any content added here will be inserted into the bottom of the section of every page. This is handy for overriding styles or adding analytics code.', - 'app_custom_html_disabled_notice' => 'Custom HTML head content is disabled on this settings page to ensure any breaking changes can be reverted.', - 'app_logo' => 'Application Logo', - 'app_logo_desc' => 'This image should be 43px in height.
Large images will be scaled down.', - 'app_primary_color' => 'Application Primary Color', - 'app_primary_color_desc' => 'Sets the primary color for the application including the banner, buttons, and links.', - 'app_homepage' => 'Application Homepage', - 'app_homepage_desc' => 'Select a view to show on the homepage instead of the default view. Page permissions are ignored for selected pages.', - 'app_homepage_select' => 'Select a page', - 'app_disable_comments' => 'Disable Comments', - 'app_disable_comments_toggle' => 'Disable comments', - 'app_disable_comments_desc' => 'Disables comments across all pages in the application.
Existing comments are not shown.', + 'app_customization' => 'Prilagajanje', + 'app_features_security' => 'Lastnosti & Varnost', + 'app_name' => 'Ime aplikacije', + 'app_name_desc' => 'To ime je prikazano v glavi in vsaki sistemski e-pošti.', + 'app_name_header' => 'Prikaži ime v glavi', + 'app_public_access' => 'Javni dostop', + 'app_public_access_desc' => 'Če omogočite to možnost, bo obiskovalcem, ki niso prijavljeni, omogočen dostop do vsebine v BookStack.', + 'app_public_access_desc_guest' => 'Dostop za javne obiskovalce je mogoče nadzorovati prek uporabnika "Gost".', + 'app_public_access_toggle' => 'Dovoli javni dostop', + 'app_public_viewing' => 'Dovoli javni pregled?', + 'app_secure_images' => 'Nalaganje slik z večjo varnostjo', + 'app_secure_images_toggle' => 'Omogoči nalaganje slik z večjo varnostjo', + 'app_secure_images_desc' => 'Zaradi delovanja so vse slike javne. Ta možnost doda naključni, hard-to-guess niz pred Url-ji slike. Prepričajte se, da indeksi imenikov niso omogočeni, da preprečite enostaven dostop.', + 'app_editor' => 'Urejevalnik strani', + 'app_editor_desc' => 'Izberite urejevalnik, ki bodo uporabniki uporabljali za urejanje strani.', + 'app_custom_html' => 'Po meri HTML vsebina glave', + 'app_custom_html_desc' => 'Katerakoli vsebina dodana tukaj, bo vstavljena na dno dela vsake strani. To je uporabno za uporabo prevladujočih slogov ali dodajanje analitike.', + 'app_custom_html_disabled_notice' => 'Po meri narejena HTML glava vsebine je onemogočena na tej strani z nastavitvami, da se zagotovi, da bodo morebitne zrušitve lahko povrnjene.', + 'app_logo' => 'Logotip aplikacije', + 'app_logo_desc' => 'Ta slika bi morala biti 43px visoka.
Velike slike bodo pomanjšane.', + 'app_primary_color' => 'Osnovna barva aplikacije', + 'app_primary_color_desc' => 'Nastavi osnovno barvo za aplikacijo vključno s pasico, gumbi in povezavami.', + 'app_homepage' => 'Domača stran aplikacije', + 'app_homepage_desc' => 'Izberi pogled, da se pokaže na domači strani, namesto osnovnega pogleda. Dovoljenja strani so prezrta za izbrane strani.', + 'app_homepage_select' => 'Izberi stran', + 'app_disable_comments' => 'Onemogoči komentarje', + 'app_disable_comments_toggle' => 'Onemogoči komentarje', + 'app_disable_comments_desc' => 'Onemogoči komentarje na vseh straneh v aplikaciji.
Obstoječi komentarji se ne prikazujejo.', // Color settings - 'content_colors' => 'Content Colors', - 'content_colors_desc' => 'Sets colors for all elements in the page organisation hierarchy. Choosing colors with a similar brightness to the default colors is recommended for readability.', - 'bookshelf_color' => 'Shelf Color', - 'book_color' => 'Book Color', - 'chapter_color' => 'Chapter Color', - 'page_color' => 'Page Color', - 'page_draft_color' => 'Page Draft Color', + 'content_colors' => 'Barve vsebine', + 'content_colors_desc' => 'Nastavi barve za vse elemente v hierarhiji. Izbor barv s podobno barvno svetlostjo je priporočljivo za osnovne barve za branje.', + 'bookshelf_color' => 'Barva police', + 'book_color' => 'knjiga barv', + 'chapter_color' => 'barvno poglavje', + 'page_color' => 'Stran barv', + 'page_draft_color' => 'stran osnutka barv', // Registration Settings - 'reg_settings' => 'Registration', - 'reg_enable' => 'Enable Registration', - 'reg_enable_toggle' => 'Enable registration', - 'reg_enable_desc' => 'When registration is enabled user will be able to sign themselves up as an application user. Upon registration they are given a single, default user role.', - 'reg_default_role' => 'Default user role after registration', - 'reg_enable_external_warning' => 'The option above is ignored while external LDAP or SAML authentication is active. User accounts for non-existing members will be auto-created if authentication, against the external system in use, is successful.', - 'reg_email_confirmation' => 'Email Confirmation', - 'reg_email_confirmation_toggle' => 'Require email confirmation', - 'reg_confirm_email_desc' => 'If domain restriction is used then email confirmation will be required and this option will be ignored.', - 'reg_confirm_restrict_domain' => 'Domain Restriction', - 'reg_confirm_restrict_domain_desc' => 'Enter a comma separated list of email domains you would like to restrict registration to. Users will be sent an email to confirm their address before being allowed to interact with the application.
Note that users will be able to change their email addresses after successful registration.', - 'reg_confirm_restrict_domain_placeholder' => 'No restriction set', + 'reg_settings' => 'registracija', + 'reg_enable' => 'onemogočena registracija', + 'reg_enable_toggle' => 'omogočena registracija', + 'reg_enable_desc' => 'Ko je registracija omogočena, se bo uporabnik lahko prijavil sam kot uporabnik aplikacije. Po registraciji je uporabniku dodeljena ena prevzeta vloga.', + 'reg_default_role' => 'prevzeta uporabniška vloga po registraciji', + 'reg_enable_external_warning' => 'Ta možnosti je ignorirana ko zunanja LDAP ali SAML avtentikacija je akitivna. Uporabniški računi za ne obstoječe uporabnike bodo avtomatsko izdelani, če avtentikacija zunanjih uporabljenih sistemov je uspešna.', + 'reg_email_confirmation' => 'potrditev e-pošte', + 'reg_email_confirmation_toggle' => 'potrebna potrditev e-pošte', + 'reg_confirm_email_desc' => 'Če uporabite omejitev domene, bo potrebna potrditev e-pošte in ta možnost bo prezrta.', + 'reg_confirm_restrict_domain' => 'omejitev domene', + 'reg_confirm_restrict_domain_desc' => 'Vnesite seznam domen, ločenih z vejico, na katere želite omejiti registracijo. Uporabnik bo prejel e-pošto za potrditev naslova, preden bo omogočena interakcija z aplikacijo.
Upoštevajte, da uporabnik po uspešni registrciji lahko spremeni svoj e-poštni naslov.', + 'reg_confirm_restrict_domain_placeholder' => 'Brez omejitev', // Maintenance settings - 'maint' => 'Maintenance', - 'maint_image_cleanup' => 'Cleanup Images', + 'maint' => 'Vzdrževanje', + 'maint_image_cleanup' => 'odstrani /počisti slike', 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.", 'maint_image_cleanup_ignore_revisions' => 'Ignore images in revisions', - 'maint_image_cleanup_run' => 'Run Cleanup', - 'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?', - 'maint_image_cleanup_success' => ':count potentially unused images found and deleted!', - 'maint_image_cleanup_nothing_found' => 'No unused images found, Nothing deleted!', - 'maint_send_test_email' => 'Send a Test Email', - 'maint_send_test_email_desc' => 'This sends a test email to your email address specified in your profile.', - 'maint_send_test_email_run' => 'Send test email', - 'maint_send_test_email_success' => 'Email sent to :address', - 'maint_send_test_email_mail_subject' => 'Test Email', - 'maint_send_test_email_mail_greeting' => 'Email delivery seems to work!', - 'maint_send_test_email_mail_text' => 'Congratulations! As you received this email notification, your email settings seem to be configured properly.', + 'maint_image_cleanup_run' => 'zaženite čiščenje', + 'maint_image_cleanup_warning' => ':zaznano je bilo število neuporabljenih slik. Ali si prepričan, da želiš odstraniti izbrane slike?', + 'maint_image_cleanup_success' => ':najdeno in izbrisano je bilo število neuporabljenih slik!', + 'maint_image_cleanup_nothing_found' => 'Najdenih ni bilo nobenih neuporabljenih slik!', + 'maint_send_test_email' => 'Pošlji testno e-pismo', + 'maint_send_test_email_desc' => 'To pošlje testno e-pošto na vaš e-poštni naslov, naveden v vašem profilu.', + 'maint_send_test_email_run' => 'Pošlji preizkusno sporočilo', + 'maint_send_test_email_success' => 'e-pošta poslana na :naslov', + 'maint_send_test_email_mail_subject' => 'Preizkusno sporočilo', + 'maint_send_test_email_mail_greeting' => 'Zdi se, da dostava e-pošte deluje!', + 'maint_send_test_email_mail_text' => 'Čestitke! Če ste prejeli e.poštno obvestilo so bile vaše e-poštne nastavitve pravilno konfigurirane.', // Role Settings - 'roles' => 'Roles', - 'role_user_roles' => 'User Roles', - 'role_create' => 'Create New Role', - 'role_create_success' => 'Role successfully created', - 'role_delete' => 'Delete Role', - 'role_delete_confirm' => 'This will delete the role with the name \':roleName\'.', + 'roles' => 'Vloge', + 'role_user_roles' => 'Pravilo uporabnika', + 'role_create' => 'Izdelaj novo polico', + 'role_create_success' => 'Zapis uspešno ustvarjen', + 'role_delete' => 'Brisanje vloge', + 'role_delete_confirm' => 'Izbrisana bo vloga z imenom \':vlogaImena\'.', 'role_delete_users_assigned' => 'This role has :userCount users assigned to it. If you would like to migrate the users from this role select a new role below.', - 'role_delete_no_migration' => "Don't migrate users", - 'role_delete_sure' => 'Are you sure you want to delete this role?', - 'role_delete_success' => 'Role successfully deleted', - 'role_edit' => 'Edit Role', - 'role_details' => 'Role Details', - 'role_name' => 'Role Name', - 'role_desc' => 'Short Description of Role', - 'role_external_auth_id' => 'External Authentication IDs', - 'role_system' => 'System Permissions', - 'role_manage_users' => 'Manage users', - 'role_manage_roles' => 'Manage roles & role permissions', - 'role_manage_entity_permissions' => 'Manage all book, chapter & page permissions', + 'role_delete_no_migration' => "Uporabniki niso prenosljivi", + 'role_delete_sure' => 'Ali ste prepričani, da želite izbrisati to element?', + 'role_delete_success' => 'Uspešno izbrisano', + 'role_edit' => 'Uredi zapis', + 'role_details' => 'Podrobnosti zapisa', + 'role_name' => 'Ime zapisa', + 'role_desc' => 'Kratki opis ', + 'role_external_auth_id' => 'Zunanje dokazilo ID', + 'role_system' => 'Sistemska dovoljenja', + 'role_manage_users' => 'Upravljanje uporabnikov', + 'role_manage_roles' => 'Vloga upravljanja & vloga dovoljenj', + 'role_manage_entity_permissions' => 'Upravljanje vseh knjig, poglavij & dovoljenj', 'role_manage_own_entity_permissions' => 'Manage permissions on own book, chapter & pages', 'role_manage_page_templates' => 'Manage page templates', 'role_access_api' => 'Access system API', - 'role_manage_settings' => 'Manage app settings', - 'role_asset' => 'Asset Permissions', + 'role_manage_settings' => 'Nastavitve za upravljanje', + 'role_asset' => 'Sistemska dovoljenja', 'role_asset_desc' => 'These permissions control default access to the assets within the system. Permissions on Books, Chapters and Pages will override these permissions.', 'role_asset_admins' => 'Admins are automatically given access to all content but these options may show or hide UI options.', - 'role_all' => 'All', + 'role_all' => 'Vse', 'role_own' => 'Own', - 'role_controlled_by_asset' => 'Controlled by the asset they are uploaded to', - 'role_save' => 'Save Role', - 'role_update_success' => 'Role successfully updated', - 'role_users' => 'Users in this role', - 'role_users_none' => 'No users are currently assigned to this role', + 'role_controlled_by_asset' => ' +46/5000 +Nadzira ga sredstvo, v katerega so naloženi', + 'role_save' => 'Shrani vlogo', + 'role_update_success' => 'Vloga uspešno posodobljena', + 'role_users' => 'Uporabniki v tej vlogi', + 'role_users_none' => ' +V tej vlogi trenutno ni dodeljen noben uporabnik', // Users - 'users' => 'Users', - 'user_profile' => 'User Profile', - 'users_add_new' => 'Add New User', - 'users_search' => 'Search Users', - 'users_details' => 'User Details', - 'users_details_desc' => 'Set a display name and an email address for this user. The email address will be used for logging into the application.', - 'users_details_desc_no_email' => 'Set a display name for this user so others can recognise them.', - 'users_role' => 'User Roles', - 'users_role_desc' => 'Select which roles this user will be assigned to. If a user is assigned to multiple roles the permissions from those roles will stack and they will receive all abilities of the assigned roles.', - 'users_password' => 'User Password', - 'users_password_desc' => 'Set a password used to log-in to the application. This must be at least 6 characters long.', - 'users_send_invite_text' => 'You can choose to send this user an invitation email which allows them to set their own password otherwise you can set their password yourself.', - 'users_send_invite_option' => 'Send user invite email', - 'users_external_auth_id' => 'External Authentication ID', - 'users_external_auth_id_desc' => 'This is the ID used to match this user when communicating with your external authentication system.', - 'users_password_warning' => 'Only fill the below if you would like to change your password.', - 'users_system_public' => 'This user represents any guest users that visit your instance. It cannot be used to log in but is assigned automatically.', - 'users_delete' => 'Delete User', - 'users_delete_named' => 'Delete user :userName', - 'users_delete_warning' => 'This will fully delete this user with the name \':userName\' from the system.', - 'users_delete_confirm' => 'Are you sure you want to delete this user?', - 'users_delete_success' => 'Users successfully removed', - 'users_edit' => 'Edit User', - 'users_edit_profile' => 'Edit Profile', - 'users_edit_success' => 'User successfully updated', - 'users_avatar' => 'User Avatar', - 'users_avatar_desc' => 'Select an image to represent this user. This should be approx 256px square.', - 'users_preferred_language' => 'Preferred Language', - 'users_preferred_language_desc' => 'This option will change the language used for the user-interface of the application. This will not affect any user-created content.', - 'users_social_accounts' => 'Social Accounts', + 'users' => 'Uporabniki', + 'user_profile' => 'Uporabniški profil', + 'users_add_new' => 'Dodaj novega uporabnika', + 'users_search' => 'Išči uporabnike', + 'users_details' => 'Podatki o uporabniku', + 'users_details_desc' => 'Nastavite prikazno ime in e-poštni naslov za tega uporabnika. E-poštni naslov bo uporabljen za prijavo v aplikacijo.', + 'users_details_desc_no_email' => ' Nastavite prikazno ime za tega uporabnika, da ga bodo drugi lahko prepoznali.', + 'users_role' => 'Vloge uporabnika', + 'users_role_desc' => 'Izberi katere vloge bodo dodeljene uporabniku. Če je uporabniku dodeljenih več vlog, se dovoljenja združijo in prejmenjo vse sposobnosti dodeljenih vlog.', + 'users_password' => 'Uporabniško geslo', + 'users_password_desc' => 'Nastavite geslo, ki se uporablja za prijavo v aplikacijo. Dolg mora biti vsaj 6 znakov.', + 'users_send_invite_text' => 'Uporabniku lahko pošljete e-poštno sporočilo s povabilom, ki mu omogoča, da nastavi svoje geslo, ali ga nastavite kar sami.', + 'users_send_invite_option' => 'Pošlji uporabniku e-povabilo', + 'users_external_auth_id' => 'Zunanje dokazilo ID', + 'users_external_auth_id_desc' => 'To je ID, s katerim se ta uporabnik ujema pri komunikaciji z vašim zunanjim sistemom za preverjanje pristnosti.', + 'users_password_warning' => 'Spodaj izpolni le, če želiš spremeniti geslo.', + 'users_system_public' => 'Ta uporabnik predstavlja vse gostujoče uporabnike, ki obiščejo vaš primer. Za prijavo je ni mogoče uporabiti, ampak je dodeljena samodejno.', + 'users_delete' => 'Brisanje uporabnika', + 'users_delete_named' => 'Brisanje uporabnika :userName', + 'users_delete_warning' => 'Iz sistema se bo popolnoma izbrisal uporabnik z imenom \':userName\'', + 'users_delete_confirm' => 'Ste prepričani, da želite izbrisati izbranega uporabnika?', + 'users_delete_success' => 'Uporabniki uspešno odstranjeni.', + 'users_edit' => 'Uredi uporabnika', + 'users_edit_profile' => 'Uredi profil', + 'users_edit_success' => 'Uporabnik uspešno posodobljen', + 'users_avatar' => 'uporabnikov avatar', + 'users_avatar_desc' => 'Izberi sliko, ki predstavlja uporabnika. Velikost mora biti približno 256px.', + 'users_preferred_language' => 'Izbrani jezik', + 'users_preferred_language_desc' => 'Ta možnost bo spremenila jezik, ki se uporablja za uporabniški vmesnik aplikacije. To ne bo vplivalo na nobeno vsebino, ki jo ustvari uporabnik.', + 'users_social_accounts' => 'Družbene ikone / računi', 'users_social_accounts_info' => 'Here you can connect your other accounts for quicker and easier login. Disconnecting an account here does not revoke previously authorized access. Revoke access from your profile settings on the connected social account.', - 'users_social_connect' => 'Connect Account', - 'users_social_disconnect' => 'Disconnect Account', - 'users_social_connected' => ':socialAccount account was successfully attached to your profile.', - 'users_social_disconnected' => ':socialAccount account was successfully disconnected from your profile.', - 'users_api_tokens' => 'API Tokens', - 'users_api_tokens_none' => 'No API tokens have been created for this user', - 'users_api_tokens_create' => 'Create Token', - 'users_api_tokens_expires' => 'Expires', - 'users_api_tokens_docs' => 'API Documentation', + 'users_social_connect' => 'Povežite račun', + 'users_social_disconnect' => 'Odklop računa', + 'users_social_connected' => ':socialAccount račun je bil uspešno dodan na vašem profilu', + 'users_social_disconnected' => ':socialAccount račun je bil uspešno odstranjen iz vašega profila', + 'users_api_tokens' => 'API žeton', + 'users_api_tokens_none' => 'Nič API žetonov ni bilo ustvarjenih za uporabnika', + 'users_api_tokens_create' => 'Ustvari žeton', + 'users_api_tokens_expires' => 'Poteče', + 'users_api_tokens_docs' => 'API dokumentacija', // API Tokens - 'user_api_token_create' => 'Create API Token', - 'user_api_token_name' => 'Name', + 'user_api_token_create' => 'Ustvari žeton', + 'user_api_token_name' => 'Ime', 'user_api_token_name_desc' => 'Give your token a readable name as a future reminder of its intended purpose.', - 'user_api_token_expiry' => 'Expiry Date', - 'user_api_token_expiry_desc' => 'Set a date at which this token expires. After this date, requests made using this token will no longer work. Leaving this field blank will set an expiry 100 years into the future.', - 'user_api_token_create_secret_message' => 'Immediately after creating this token a "Token ID"" & "Token Secret" will be generated and displayed. The secret will only be shown a single time so be sure to copy the value to somewhere safe and secure before proceeding.', - 'user_api_token_create_success' => 'API token successfully created', - 'user_api_token_update_success' => 'API token successfully updated', - 'user_api_token' => 'API Token', - 'user_api_token_id' => 'Token ID', + 'user_api_token_expiry' => 'Datum poteka', + 'user_api_token_expiry_desc' => 'Določi datum izteka uporabnosti žetona. Po tem datumu, zahteve poslane s tem žetonom, ne bodo več delovale. +Če pustite to polje prazno, bo iztek uporabnosti 100.let .', + 'user_api_token_create_secret_message' => 'Takoj po ustvarjanju tega žetona se ustvari in prikaže "Token ID" "in" Token Secret ". Skrivnost bo prikazana samo enkrat, zato se pred nadaljevanjem prepričajte o varnosti kopirnega mesta.', + 'user_api_token_create_success' => 'API žeton uspešno ustvarjen', + 'user_api_token_update_success' => 'API žeton uspešno posodobljen', + 'user_api_token' => 'API žeton', + 'user_api_token_id' => 'Žeton ID', 'user_api_token_id_desc' => 'This is a non-editable system generated identifier for this token which will need to be provided in API requests.', - 'user_api_token_secret' => 'Token Secret', + 'user_api_token_secret' => 'Skrivnost žetona', 'user_api_token_secret_desc' => 'This is a system generated secret for this token which will need to be provided in API requests. This will only be displayed this one time so copy this value to somewhere safe and secure.', - 'user_api_token_created' => 'Token Created :timeAgo', - 'user_api_token_updated' => 'Token Updated :timeAgo', - 'user_api_token_delete' => 'Delete Token', - 'user_api_token_delete_warning' => 'This will fully delete this API token with the name \':tokenName\' from the system.', - 'user_api_token_delete_confirm' => 'Are you sure you want to delete this API token?', - 'user_api_token_delete_success' => 'API token successfully deleted', + 'user_api_token_created' => 'Žeton ustvarjen :timeAgo', + 'user_api_token_updated' => 'Žeton posodobljen :timeAgo', + 'user_api_token_delete' => 'Briši žeton', + 'user_api_token_delete_warning' => 'Iz sistema se bo popolnoma izbrisal API žeton z imenom \':tokenName\' ', + 'user_api_token_delete_confirm' => 'Ali ste prepričani, da želite izbrisati ta API žeton?', + 'user_api_token_delete_success' => 'API žeton uspešno izbrisan', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. @@ -186,7 +190,7 @@ return [ 'en' => 'English', 'ar' => 'العربية', 'cs' => 'Česky', - 'da' => 'Dansk', + 'da' => 'danščina', 'de' => 'Deutsch (Sie)', 'de_informal' => 'Deutsch (Du)', 'es' => 'Español', @@ -201,6 +205,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/sl/validation.php b/resources/lang/sl/validation.php index 76b57a2a3..fec6d5602 100644 --- a/resources/lang/sl/validation.php +++ b/resources/lang/sl/validation.php @@ -8,104 +8,104 @@ return [ // Standard laravel validation lines - 'accepted' => 'The :attribute must be accepted.', - 'active_url' => 'The :attribute is not a valid URL.', - 'after' => 'The :attribute must be a date after :date.', - 'alpha' => 'The :attribute may only contain letters.', - 'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.', - 'alpha_num' => 'The :attribute may only contain letters and numbers.', - 'array' => 'The :attribute must be an array.', - 'before' => 'The :attribute must be a date before :date.', + 'accepted' => ':attribute mora biti potrjen.', + 'active_url' => ':attribute ni veljaven URL.', + 'after' => ':attribute mora biti datum po :date.', + 'alpha' => ':attribute lahko vsebuje samo črke.', + 'alpha_dash' => ':attribute lahko vsebuje samo ?rke, ?tevilke in ?rtice.', + 'alpha_num' => ':attribute lahko vsebuje samo črke in številke.', + 'array' => ':attribute mora biti niz.', + 'before' => ':attribute mora biti datum pred :date.', 'between' => [ - 'numeric' => 'The :attribute must be between :min and :max.', - 'file' => 'The :attribute must be between :min and :max kilobytes.', - 'string' => 'The :attribute must be between :min and :max characters.', - 'array' => 'The :attribute must have between :min and :max items.', + 'numeric' => ':attribute mora biti med :min in :max.', + 'file' => ':attribute mora biti med :min in :max kilobajti.', + 'string' => ':attribute mora biti med :min in :max znaki.', + 'array' => ':attribute mora imeti med :min in :max elementov.', ], - 'boolean' => 'The :attribute field must be true or false.', - 'confirmed' => 'The :attribute confirmation does not match.', - 'date' => 'The :attribute is not a valid date.', - 'date_format' => 'The :attribute does not match the format :format.', - 'different' => 'The :attribute and :other must be different.', - 'digits' => 'The :attribute must be :digits digits.', - 'digits_between' => 'The :attribute must be between :min and :max digits.', - 'email' => 'The :attribute must be a valid email address.', - 'ends_with' => 'The :attribute must end with one of the following: :values', - 'filled' => 'The :attribute field is required.', + 'boolean' => ':attribute polje mora biti pravilno ali napačno.', + 'confirmed' => ':attribute potrditev se ne ujema.', + 'date' => ':attribute ni veljaven datum.', + 'date_format' => ':attribute se ne ujema z obliko :format.', + 'different' => ':attribute in :other morata biti različna.', + 'digits' => 'Atribut mora biti: števnik.', + 'digits_between' => ':attribute mora biti med :min in :max števkami.', + 'email' => ':attribute mora biti veljaven e-naslov.', + 'ends_with' => 'The :attribute se mora končati z eno od določenih: :vrednost/values', + 'filled' => 'Polje ne sme biti prazno.', 'gt' => [ - 'numeric' => 'The :attribute must be greater than :value.', - 'file' => 'The :attribute must be greater than :value kilobytes.', - 'string' => 'The :attribute must be greater than :value characters.', - 'array' => 'The :attribute must have more than :value items.', + 'numeric' => ':attribute mora biti večji kot :vrednost.', + 'file' => ':attribute mora biti večji kot :vrednost kilobytes', + 'string' => ':attribute mora biti večji kot :vrednost znakov', + 'array' => ':attribute mora biti večji kot :vrednost znakov', ], 'gte' => [ - 'numeric' => 'The :attribute must be greater than or equal :value.', - 'file' => 'The :attribute must be greater than or equal :value kilobytes.', - 'string' => 'The :attribute must be greater than or equal :value characters.', - 'array' => 'The :attribute must have :value items or more.', + 'numeric' => ':attribute mora biti večji kot ali enak :vrednost.', + 'file' => ':attribute mora biti večji kot ali enak :vrednost kilobytes', + 'string' => ':attribute mora biti večji kot ali enak :vrednost znakov', + 'array' => ':attribute mora imeti :vrednost znakov ali več', ], - 'exists' => 'The selected :attribute is invalid.', - 'image' => 'The :attribute must be an image.', - 'image_extension' => 'The :attribute must have a valid & supported image extension.', - 'in' => 'The selected :attribute is invalid.', - 'integer' => 'The :attribute must be an integer.', - 'ip' => 'The :attribute must be a valid IP address.', - 'ipv4' => 'The :attribute must be a valid IPv4 address.', - 'ipv6' => 'The :attribute must be a valid IPv6 address.', - 'json' => 'The :attribute must be a valid JSON string.', + 'exists' => 'Izbrani atribut je neveljaven.', + 'image' => ':attribute mora biti slika.', + 'image_extension' => ':attribute mora imeti veljavno & podprto slikovno pripono', + 'in' => 'izbran :attribute je neveljaven.', + 'integer' => ':attribute mora biti celo število.', + 'ip' => ':attribute mora biti veljaven IP naslov.', + 'ipv4' => ':attribute mora biti veljaven IPv4 naslov.', + 'ipv6' => ':attribute mora biti veljaven IPv6 naslov.', + 'json' => ':attribute mora biti veljavna JSON povezava.', 'lt' => [ - 'numeric' => 'The :attribute must be less than :value.', - 'file' => 'The :attribute must be less than :value kilobytes.', - 'string' => 'The :attribute must be less than :value characters.', - 'array' => 'The :attribute must have less than :value items.', + 'numeric' => ':attribute mora biti manj kot :vrednost.', + 'file' => ':attribute mora biti manj kot :vrednost kilobytes', + 'string' => ':attribute mora biti manj kot :vrednost znakov', + 'array' => ':attribute mora imeti manj kot :vrednost znakov', ], 'lte' => [ - 'numeric' => 'The :attribute must be less than or equal :value.', - 'file' => 'The :attribute must be less than or equal :value kilobytes.', - 'string' => 'The :attribute must be less than or equal :value characters.', - 'array' => 'The :attribute must not have more than :value items.', + 'numeric' => ':attribute mora biti manj kot ali enak :vrednost.', + 'file' => ':attribute mora biti manj kot ali enak :vrednost kilobytes', + 'string' => ':attribute mora biti manj kot ali enak :vrednost znakov', + 'array' => ':attribute ne sme imeti več kot :vrednost elementov', ], 'max' => [ - 'numeric' => 'The :attribute may not be greater than :max.', - 'file' => 'The :attribute may not be greater than :max kilobytes.', - 'string' => 'The :attribute may not be greater than :max characters.', - 'array' => 'The :attribute may not have more than :max items.', + 'numeric' => ':attribute ne sme biti večja od :max.', + 'file' => ':attribute ne sme biti večja od :max kilobytes.', + 'string' => 'Atribut naj ne bo večji od: max znakov.', + 'array' => ':attribute ne sme imeti več kot :max elementov.', ], - 'mimes' => 'The :attribute must be a file of type: :values.', + 'mimes' => 'Atribut mora biti datoteka vrste:: vrednost.', 'min' => [ - 'numeric' => 'The :attribute must be at least :min.', - 'file' => 'The :attribute must be at least :min kilobytes.', - 'string' => 'The :attribute must be at least :min characters.', - 'array' => 'The :attribute must have at least :min items.', + 'numeric' => ':attribute mora biti najmanj :min.', + 'file' => ':attribute mora biti najmanj :min KB.', + 'string' => ':attribute mora biti najmanj :min znakov.', + 'array' => ':attribute mora imeti vsaj :min elementov.', ], - 'no_double_extension' => 'The :attribute must only have a single file extension.', - 'not_in' => 'The selected :attribute is invalid.', - 'not_regex' => 'The :attribute format is invalid.', - 'numeric' => 'The :attribute must be a number.', - 'regex' => 'The :attribute format is invalid.', - 'required' => 'The :attribute field is required.', - 'required_if' => 'The :attribute field is required when :other is :value.', - 'required_with' => 'The :attribute field is required when :values is present.', - 'required_with_all' => 'The :attribute field is required when :values is present.', - 'required_without' => 'The :attribute field is required when :values is not present.', - 'required_without_all' => 'The :attribute field is required when none of :values are present.', - 'same' => 'The :attribute and :other must match.', + 'no_double_extension' => ':attribute mora imeti samo eno razširitveno datoteko', + 'not_in' => 'Izbrani atribut je neveljaven.', + 'not_regex' => ':attribute oblika ni veljavna.', + 'numeric' => 'Atribut mora biti število.', + 'regex' => ':attribute oblika ni veljavna.', + 'required' => 'Polje :attribute je obvezno.', + 'required_if' => 'Polje atributa je obvezno, če: drugo je: vrednost.', + 'required_with' => 'Polje atributa je obvezno, ko: so prisotne vrednosti.', + 'required_with_all' => 'Polje atributa je obvezno, ko: so prisotne vrednosti.', + 'required_without' => 'Polje atributa je obvezno, če: vrednosti niso prisotne.', + 'required_without_all' => 'Polje atributa je obvezno, če nobena od: vrednosti ni prisotna.', + 'same' => 'Atribut in: drugi se morajo ujemati.', 'size' => [ - 'numeric' => 'The :attribute must be :size.', - 'file' => 'The :attribute must be :size kilobytes.', - 'string' => 'The :attribute must be :size characters.', - 'array' => 'The :attribute must contain :size items.', + 'numeric' => ':attribute mora biti :velikost.', + 'file' => ':attribute mora biti :velikost KB.', + 'string' => 'Atribut mora biti: velikost znakov.', + 'array' => ':attribute mora vsebovati :velikost elementov.', ], - 'string' => 'The :attribute must be a string.', - 'timezone' => 'The :attribute must be a valid zone.', - 'unique' => 'The :attribute has already been taken.', - 'url' => 'The :attribute format is invalid.', - 'uploaded' => 'The file could not be uploaded. The server may not accept files of this size.', + 'string' => ':attribute mora biti niz.', + 'timezone' => ':attribute mora biti veljavna cona.', + 'unique' => ':attribute je že zaseden.', + 'url' => ':attribute oblika ni veljavna.', + 'uploaded' => 'Datoteke ni bilo mogoče naložiti. Strežnik morda ne sprejema datotek te velikosti.', // Custom validation lines 'custom' => [ 'password-confirm' => [ - 'required_with' => 'Password confirmation required', + 'required_with' => 'Potrditev gesla', ], ], diff --git a/resources/lang/sv/entities.php b/resources/lang/sv/entities.php index e0cdb3ce6..e4938fbfd 100644 --- a/resources/lang/sv/entities.php +++ b/resources/lang/sv/entities.php @@ -17,12 +17,12 @@ return [ 'recent_activity' => 'Aktivitet', 'create_now' => 'Skapa en nu', 'revisions' => 'Revisioner', - 'meta_revision' => 'Revision #:revisionCount', + 'meta_revision' => 'Revisions #:revisionCount', 'meta_created' => 'Skapad :timeLength', 'meta_created_name' => 'Skapad :timeLength av :user', 'meta_updated' => 'Uppdaterad :timeLength', 'meta_updated_name' => 'Uppdaterad :timeLength av :user', - 'entity_select' => 'Entity Select', + 'entity_select' => 'Välj enhet', 'images' => 'Bilder', 'my_recent_drafts' => 'Mina nyaste utkast', 'my_recently_viewed' => 'Mina senast visade sidor', @@ -210,7 +210,7 @@ return [ 'pages_revisions_created_by' => 'Skapad av', 'pages_revisions_date' => 'Revisionsdatum', 'pages_revisions_number' => '#', - 'pages_revisions_numbered' => 'Revision #:id', + 'pages_revisions_numbered' => 'Revisions #:id', 'pages_revisions_numbered_changes' => 'Revision #:id ändringar', 'pages_revisions_changelog' => 'Ändringslogg', 'pages_revisions_changes' => 'Ändringar', @@ -234,7 +234,7 @@ return [ ], 'pages_draft_discarded' => 'Utkastet har tagits bort. Redigeringsverktyget har uppdaterats med aktuellt innehåll.', 'pages_specific' => 'Specifik sida', - 'pages_is_template' => 'Page Template', + 'pages_is_template' => 'Sidmall', // Editor Sidebar 'page_tags' => 'Sidtaggar', @@ -243,11 +243,11 @@ return [ 'shelf_tags' => 'Hylltaggar', 'tag' => 'Tagg', 'tags' => 'Taggar', - 'tag_name' => 'Tag Name', + 'tag_name' => 'Etikettnamn', 'tag_value' => 'Taggvärde (Frivilligt)', 'tags_explain' => "Lägg till taggar för att kategorisera ditt innehåll bättre. \n Du kan tilldela ett värde till en tagg för ännu bättre organisering.", 'tags_add' => 'Lägg till ännu en tagg', - 'tags_remove' => 'Remove this tag', + 'tags_remove' => 'Ta bort denna etikett', 'attachments' => 'Bilagor', 'attachments_explain' => 'Ladda upp filer eller bifoga länkar till ditt innehåll. Dessa visas i sidokolumnen.', 'attachments_explain_instant_save' => 'Ändringar här sparas omgående.', @@ -273,12 +273,12 @@ return [ 'attachments_file_uploaded' => 'Filen har laddats upp', 'attachments_file_updated' => 'Filen har uppdaterats', 'attachments_link_attached' => 'Länken har bifogats till sidan', - 'templates' => 'Templates', - 'templates_set_as_template' => 'Page is a template', - 'templates_explain_set_as_template' => 'You can set this page as a template so its contents be utilized when creating other pages. Other users will be able to use this template if they have view permissions for this page.', - 'templates_replace_content' => 'Replace page content', - 'templates_append_content' => 'Append to page content', - 'templates_prepend_content' => 'Prepend to page content', + 'templates' => 'Mallar', + 'templates_set_as_template' => 'Sidan är en mall', + 'templates_explain_set_as_template' => 'Du kan använda denna sida som en mall så att dess innehåll kan användas när du skapar andra sidor. Andra användare kommer att kunna använda denna mall om de har visningsrättigheter för den här sidan.', + 'templates_replace_content' => 'Ersätt sidinnehåll', + 'templates_append_content' => 'Lägg till till sidans innehåll', + 'templates_prepend_content' => 'Lägg till före sidans innehåll', // Profile View 'profile_user_for_x' => 'Användare i :time', diff --git a/resources/lang/sv/errors.php b/resources/lang/sv/errors.php index 69baa7999..adf22af1d 100644 --- a/resources/lang/sv/errors.php +++ b/resources/lang/sv/errors.php @@ -13,16 +13,16 @@ return [ 'email_already_confirmed' => 'E-posten har redan bekräftats, prova att logga in.', 'email_confirmation_invalid' => 'Denna bekräftelsekod är inte giltig eller har redan använts. Vänligen prova att registera dig på nytt', 'email_confirmation_expired' => 'Denna bekräftelsekod har gått ut. Vi har skickat dig en ny.', - 'email_confirmation_awaiting' => 'The email address for the account in use needs to be confirmed', + 'email_confirmation_awaiting' => 'E-postadressen för det konto som används måste bekräftas', 'ldap_fail_anonymous' => 'LDAP-inloggning misslyckades med anonym bindning', 'ldap_fail_authed' => 'LDAP-inloggning misslyckades med angivna dn- och lösenordsuppgifter', 'ldap_extension_not_installed' => 'LDAP PHP-tillägg inte installerat', 'ldap_cannot_connect' => 'Kan inte ansluta till ldap-servern. Anslutningen misslyckades', - 'saml_already_logged_in' => 'Already logged in', - 'saml_user_not_registered' => 'The user :name is not registered and automatic registration is disabled', - 'saml_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system', - 'saml_invalid_response_id' => 'The request from the external authentication system is not recognised by a process started by this application. Navigating back after a login could cause this issue.', - 'saml_fail_authed' => 'Login using :system failed, system did not provide successful authorization', + 'saml_already_logged_in' => 'Redan inloggad', + 'saml_user_not_registered' => 'Användarnamnet är inte registrerat och automatisk registrering är inaktiverad', + 'saml_no_email_address' => 'Kunde inte hitta en e-postadress för den här användaren i data som tillhandahålls av det externa autentiseringssystemet', + 'saml_invalid_response_id' => 'En begäran från det externa autentiseringssystemet känns inte igen av en process som startats av denna applikation. Att navigera bakåt efter en inloggning kan orsaka detta problem.', + 'saml_fail_authed' => 'Inloggning med :system misslyckades, systemet godkände inte auktoriseringen', 'social_no_action_defined' => 'Ingen åtgärd definierad', 'social_login_bad_response' => "Ett fel inträffade vid inloggning genom :socialAccount: \n:error", 'social_account_in_use' => 'Detta konto från :socialAccount används redan. Testa att logga in med :socialAccount istället.', @@ -33,7 +33,7 @@ return [ 'social_account_register_instructions' => 'Om du inte har något konto ännu kan du registerar dig genom att välja :socialAccount.', 'social_driver_not_found' => 'Drivrutinen för den här tjänsten hittades inte', 'social_driver_not_configured' => 'Dina inställningar för :socialAccount är inte korrekta.', - 'invite_token_expired' => 'This invitation link has expired. You can instead try to reset your account password.', + 'invite_token_expired' => 'Denna inbjudningslänk har löpt ut. Du kan istället försöka återställa ditt kontos lösenord.', // System 'path_not_writable' => 'Kunde inte ladda upp till sökvägen :filePath. Kontrollera att webbservern har skrivåtkomst.', @@ -83,21 +83,21 @@ return [ // Error pages '404_page_not_found' => 'Sidan hittades inte', 'sorry_page_not_found' => 'Tyvärr gick det inte att hitta sidan du söker.', - 'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.', + 'sorry_page_not_found_permission_warning' => 'Om du förväntade dig att denna sida skulle existera, kanske du inte har behörighet att se den.', 'return_home' => 'Återvänd till startsidan', 'error_occurred' => 'Ett fel inträffade', 'app_down' => ':appName är nere just nu', 'back_soon' => 'Vi är snart tillbaka.', // API errors - 'api_no_authorization_found' => 'No authorization token found on the request', - 'api_bad_authorization_format' => 'An authorization token was found on the request but the format appeared incorrect', - 'api_user_token_not_found' => 'No matching API token was found for the provided authorization token', - 'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect', - 'api_user_no_api_permission' => 'The owner of the used API token does not have permission to make API calls', - 'api_user_token_expired' => 'The authorization token used has expired', + 'api_no_authorization_found' => 'Ingen auktoriseringstoken hittades på denna begäran', + 'api_bad_authorization_format' => 'En auktoriseringstoken hittades på denna begäran men formatet verkade felaktigt', + 'api_user_token_not_found' => 'Ingen matchande API-token hittades för den angivna auktoriseringstoken', + 'api_incorrect_token_secret' => 'Hemligheten för den angivna API-token är felaktig', + 'api_user_no_api_permission' => 'Ägaren av den använda API-token har inte behörighet att göra API-anrop', + 'api_user_token_expired' => 'Den använda auktoriseringstoken har löpt ut', // Settings & Maintenance - 'maintenance_test_email_failure' => 'Error thrown when sending a test email:', + 'maintenance_test_email_failure' => 'Ett fel uppstod när ett test mail skulle skickas:', ]; diff --git a/resources/lang/sv/settings.php b/resources/lang/sv/settings.php index 5ad6ec587..05284cc5a 100644 --- a/resources/lang/sv/settings.php +++ b/resources/lang/sv/settings.php @@ -29,7 +29,7 @@ return [ 'app_editor_desc' => 'Välj vilket redigeringsverktyg som ska användas av alla användare för att redigera sidor.', 'app_custom_html' => 'Egen HTML i ', 'app_custom_html_desc' => 'Eventuellt innehåll i det här fältet placeras längst ner i -sektionen på varje sida. Detta är användbart för att skriva över stilmaller eller lägga in spårningskoder.', - 'app_custom_html_disabled_notice' => 'Custom HTML head content is disabled on this settings page to ensure any breaking changes can be reverted.', + 'app_custom_html_disabled_notice' => 'Anpassat innehåll i HTML-huvud är inaktiverat på denna inställningssida för att säkerställa att eventuella ändringar som påverkar funktionaliteten kan återställas.', 'app_logo' => 'Applikationslogotyp', 'app_logo_desc' => 'Bilden bör vara minst 43px hög.
Större bilder skalas ner.', 'app_primary_color' => 'Primärfärg', @@ -42,13 +42,13 @@ return [ 'app_disable_comments_desc' => 'Inaktivera kommentarer på alla sidor i applikationen. Befintliga kommentarer visas inte.', // Color settings - 'content_colors' => 'Content Colors', - 'content_colors_desc' => 'Sets colors for all elements in the page organisation hierarchy. Choosing colors with a similar brightness to the default colors is recommended for readability.', - 'bookshelf_color' => 'Shelf Color', - 'book_color' => 'Book Color', - 'chapter_color' => 'Chapter Color', - 'page_color' => 'Page Color', - 'page_draft_color' => 'Page Draft Color', + 'content_colors' => 'Innehållsfärger', + 'content_colors_desc' => 'Ställer in färger för alla element i sidornas hierarki. Att välja färger med samma ljusstyrka som standardfärgerna rekommenderas för läsbarhet.', + 'bookshelf_color' => 'Hyllfärg', + 'book_color' => 'Bokens färg', + 'chapter_color' => 'Kapitels färg', + 'page_color' => 'Sidfärg', + 'page_draft_color' => 'Färg på sidutkast', // Registration Settings 'reg_settings' => 'Registreringsinställningar', @@ -56,7 +56,7 @@ return [ 'reg_enable_toggle' => 'Tillåt registrering', 'reg_enable_desc' => 'När registrering tillåts kan användaren logga in som en användare. Vid registreringen ges de en förvald användarroll.', 'reg_default_role' => 'Standardroll efter registrering', - 'reg_enable_external_warning' => 'The option above is ignored while external LDAP or SAML authentication is active. User accounts for non-existing members will be auto-created if authentication, against the external system in use, is successful.', + 'reg_enable_external_warning' => 'Alternativet ovan ignoreras medan extern LDAP eller SAML-autentisering är aktiv. Användarkonton för icke-existerande medlemmar kommer att skapas automatiskt om autentisering mot det externa system som används lyckas.', 'reg_email_confirmation' => 'E-postbekräftelse', 'reg_email_confirmation_toggle' => 'Kräv e-postbekräftelse', 'reg_confirm_email_desc' => 'Om registrering begränas till vissa domäner kommer e-postbekräftelse alltid att krävas och den här inställningen kommer att ignoreras.', @@ -74,12 +74,12 @@ return [ 'maint_image_cleanup_success' => 'Hittade och raderade :count bilder som potentiellt inte används!', 'maint_image_cleanup_nothing_found' => 'Hittade inga oanvända bilder, så inget har raderats!', 'maint_send_test_email' => 'Skicka ett testmail', - 'maint_send_test_email_desc' => 'This sends a test email to your email address specified in your profile.', + 'maint_send_test_email_desc' => 'Detta skickar ett testmeddelande till den e-postadress som anges i din profil.', 'maint_send_test_email_run' => 'Skicka testmail', - 'maint_send_test_email_success' => 'Email sent to :address', - 'maint_send_test_email_mail_subject' => 'Test Email', - 'maint_send_test_email_mail_greeting' => 'Email delivery seems to work!', - 'maint_send_test_email_mail_text' => 'Congratulations! As you received this email notification, your email settings seem to be configured properly.', + 'maint_send_test_email_success' => 'E-post skickat till :address', + 'maint_send_test_email_mail_subject' => 'Testmejl', + 'maint_send_test_email_mail_greeting' => 'E-postleverans verkar fungera!', + 'maint_send_test_email_mail_text' => 'Grattis! Eftersom du fick detta e-postmeddelande verkar dina e-postinställningar vara korrekt konfigurerade.', // Role Settings 'roles' => 'Roller', @@ -102,8 +102,8 @@ return [ 'role_manage_roles' => 'Hantera roller & rättigheter', 'role_manage_entity_permissions' => 'Hantera rättigheter för alla böcker, kapitel och sidor', 'role_manage_own_entity_permissions' => 'Hantera rättigheter för egna böcker, kapitel och sidor', - 'role_manage_page_templates' => 'Manage page templates', - 'role_access_api' => 'Access system API', + 'role_manage_page_templates' => 'Hantera mallar', + 'role_access_api' => 'Åtkomst till systemets API', 'role_manage_settings' => 'Hantera appinställningar', 'role_asset' => 'Tillgång till innehåll', 'role_asset_desc' => 'Det här är standardinställningarna för allt innehåll i systemet. Eventuella anpassade rättigheter på böcker, kapitel och sidor skriver över dessa inställningar.', @@ -128,10 +128,10 @@ return [ 'users_role_desc' => 'Välj vilka roller den här användaren ska tilldelas. Om en användare har tilldelats flera roller kommer behörigheterna från dessa roller att staplas och de kommer att få alla rättigheter i de tilldelade rollerna.', 'users_password' => 'Användarlösenord', 'users_password_desc' => 'Ange ett lösenord som ska användas för att logga in på sidan. Lösenordet måste vara minst 5 tecken långt.', - 'users_send_invite_text' => 'You can choose to send this user an invitation email which allows them to set their own password otherwise you can set their password yourself.', - 'users_send_invite_option' => 'Send user invite email', + 'users_send_invite_text' => 'Du kan välja att skicka denna användare ett e-postmeddelande som tillåter dem att ställa in sitt eget lösenord, eller så kan du ställa in deras lösenord själv.', + 'users_send_invite_option' => 'Skicka e-post med inbjudan', 'users_external_auth_id' => 'Externt ID för autentisering', - 'users_external_auth_id_desc' => 'This is the ID used to match this user when communicating with your external authentication system.', + 'users_external_auth_id_desc' => 'Detta är det ID som används för att matcha denna användare när du kommunicerar med ditt externa autentiseringssystem.', 'users_password_warning' => 'Fyll i nedanstående fält endast om du vill byta lösenord:', 'users_system_public' => 'Den här användaren representerar eventuella gäster som använder systemet. Den kan inte användas för att logga in utan tilldeles automatiskt.', 'users_delete' => 'Ta bort användare', @@ -152,32 +152,32 @@ return [ 'users_social_disconnect' => 'Koppla från konto', 'users_social_connected' => ':socialAccount har kopplats till ditt konto.', 'users_social_disconnected' => ':socialAccount har kopplats bort från ditt konto.', - 'users_api_tokens' => 'API Tokens', - 'users_api_tokens_none' => 'No API tokens have been created for this user', - 'users_api_tokens_create' => 'Create Token', - 'users_api_tokens_expires' => 'Expires', - 'users_api_tokens_docs' => 'API Documentation', + 'users_api_tokens' => 'API-nyckel', + 'users_api_tokens_none' => 'Inga API-tokens har skapats för den här användaren', + 'users_api_tokens_create' => 'Skapa token', + 'users_api_tokens_expires' => 'Förfaller', + 'users_api_tokens_docs' => 'API-dokumentation', // API Tokens - 'user_api_token_create' => 'Create API Token', - 'user_api_token_name' => 'Name', - 'user_api_token_name_desc' => 'Give your token a readable name as a future reminder of its intended purpose.', - 'user_api_token_expiry' => 'Expiry Date', - 'user_api_token_expiry_desc' => 'Set a date at which this token expires. After this date, requests made using this token will no longer work. Leaving this field blank will set an expiry 100 years into the future.', - 'user_api_token_create_secret_message' => 'Immediately after creating this token a "Token ID"" & "Token Secret" will be generated and displayed. The secret will only be shown a single time so be sure to copy the value to somewhere safe and secure before proceeding.', - 'user_api_token_create_success' => 'API token successfully created', - 'user_api_token_update_success' => 'API token successfully updated', - 'user_api_token' => 'API Token', + 'user_api_token_create' => 'Skapa API-nyckel', + 'user_api_token_name' => 'Namn', + 'user_api_token_name_desc' => 'Ge din token ett läsbart namn som en framtida påminnelse om dess avsedda syfte.', + 'user_api_token_expiry' => 'Förfallodatum', + 'user_api_token_expiry_desc' => 'Ange ett datum då denna token går ut. Efter detta datum kommer förfrågningar som görs med denna token inte längre att fungera. Lämnar du detta fält tomt kommer utgångsdatum att sättas 100 år in i framtiden.', + 'user_api_token_create_secret_message' => 'Omedelbart efter att du skapat denna token kommer ett "Token ID" & "Token Secret" att genereras och visas. Token Secret kommer bara att visas en enda gång så se till att kopiera värdet till en säker plats innan du fortsätter.', + 'user_api_token_create_success' => 'API-token har skapats', + 'user_api_token_update_success' => 'API-token har uppdaterats', + 'user_api_token' => 'API-nyckel', 'user_api_token_id' => 'Token ID', - 'user_api_token_id_desc' => 'This is a non-editable system generated identifier for this token which will need to be provided in API requests.', + 'user_api_token_id_desc' => 'Detta är en icke-redigerbar systemgenererad identifierare för denna token som måste tillhandahållas i API-förfrågningar.', 'user_api_token_secret' => 'Token Secret', - 'user_api_token_secret_desc' => 'This is a system generated secret for this token which will need to be provided in API requests. This will only be displayed this one time so copy this value to somewhere safe and secure.', - 'user_api_token_created' => 'Token Created :timeAgo', - 'user_api_token_updated' => 'Token Updated :timeAgo', - 'user_api_token_delete' => 'Delete Token', - 'user_api_token_delete_warning' => 'This will fully delete this API token with the name \':tokenName\' from the system.', - 'user_api_token_delete_confirm' => 'Are you sure you want to delete this API token?', - 'user_api_token_delete_success' => 'API token successfully deleted', + 'user_api_token_secret_desc' => 'Detta är en systemgenererad hemlighet för denna token som måste tillhandahållas i API-förfrågningar. Denna kommer bara att visas en gång så kopiera detta värde till en säker plats.', + 'user_api_token_created' => 'Token skapad :timeAgo', + 'user_api_token_updated' => 'Token Uppdaterad :timeAgo', + 'user_api_token_delete' => 'Ta bort token', + 'user_api_token_delete_warning' => 'Detta kommer att helt ta bort denna API-token med namnet \':tokenName\' från systemet.', + 'user_api_token_delete_confirm' => 'Är du säker på att du vill ta bort denna API-token?', + 'user_api_token_delete_success' => 'API-token har tagits bort', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. @@ -186,7 +186,7 @@ return [ 'en' => 'English', 'ar' => 'العربية', 'cs' => 'Česky', - 'da' => 'Dansk', + 'da' => 'Danska', 'de' => 'Deutsch (Sie)', 'de_informal' => 'Deutsch (Du)', 'es' => 'Español', @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenska', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/sv/validation.php b/resources/lang/sv/validation.php index 490d1d85b..5da78b245 100644 --- a/resources/lang/sv/validation.php +++ b/resources/lang/sv/validation.php @@ -30,19 +30,19 @@ return [ 'digits' => ':attribute måste vara :digits siffror.', 'digits_between' => ':attribute måste vara mellan :min och :max siffror.', 'email' => ':attribute måste vara en giltig e-postadress.', - 'ends_with' => 'The :attribute must end with one of the following: :values', + 'ends_with' => ':attribute måste sluta med något av följande: :values', 'filled' => ':attribute är obligatoriskt.', 'gt' => [ - 'numeric' => 'The :attribute must be greater than :value.', - 'file' => 'The :attribute must be greater than :value kilobytes.', - 'string' => 'The :attribute must be greater than :value characters.', - 'array' => 'The :attribute must have more than :value items.', + 'numeric' => ':attribute måste vara större än :value.', + 'file' => ':attribute måste vara större än :value kilobytes.', + 'string' => ':attribute måste vara större än :value tecken.', + 'array' => ':attribute måste ha mer än :value objekt.', ], 'gte' => [ - 'numeric' => 'The :attribute must be greater than or equal :value.', - 'file' => 'The :attribute must be greater than or equal :value kilobytes.', - 'string' => 'The :attribute must be greater than or equal :value characters.', - 'array' => 'The :attribute must have :value items or more.', + 'numeric' => ':attribute måste vara större än eller likamed :value.', + 'file' => ':attribute måste vara större än eller lika med :value kilobytes.', + 'string' => ':attribute måste vara större än eller lika med :value tecken.', + 'array' => ':attribute måste ha :value objekt eller mer.', ], 'exists' => 'Valt värde för :attribute är ogiltigt.', 'image' => ':attribute måste vara en bild.', @@ -50,20 +50,20 @@ return [ 'in' => 'Vald :attribute är ogiltigt.', 'integer' => ':attribute måste vara en integer.', 'ip' => ':attribute måste vara en giltig IP-adress.', - 'ipv4' => 'The :attribute must be a valid IPv4 address.', - 'ipv6' => 'The :attribute must be a valid IPv6 address.', - 'json' => 'The :attribute must be a valid JSON string.', + 'ipv4' => ':attribute måste vara en giltig IPv4-adress.', + 'ipv6' => ':attribute måste vara en giltig IPv6-adress.', + 'json' => ':attribute måste vara en giltig JSON-sträng.', 'lt' => [ - 'numeric' => 'The :attribute must be less than :value.', - 'file' => 'The :attribute must be less than :value kilobytes.', - 'string' => 'The :attribute must be less than :value characters.', - 'array' => 'The :attribute must have less than :value items.', + 'numeric' => ':attribute måste vara mindre än :value.', + 'file' => ':attribute måste vara mindre än :value kilobytes.', + 'string' => ':attribute måste vara mindre än :value tecken.', + 'array' => ':attribute måste ha mindre än :value objekt.', ], 'lte' => [ - 'numeric' => 'The :attribute must be less than or equal :value.', - 'file' => 'The :attribute must be less than or equal :value kilobytes.', - 'string' => 'The :attribute must be less than or equal :value characters.', - 'array' => 'The :attribute must not have more than :value items.', + 'numeric' => ':attribute måste vara mindre än eller lika :value.', + 'file' => ':attribute måste vara mindre än eller lika med :value kilobytes.', + 'string' => ':attribute måste vara mindre än eller lika med :value tecken.', + 'array' => ':attribute får inte innehålla mer än :max objekt.', ], 'max' => [ 'numeric' => ':attribute får inte vara större än :max.', @@ -80,7 +80,7 @@ return [ ], 'no_double_extension' => ':attribute får bara ha ett filtillägg.', 'not_in' => 'Vald :attribute är inte giltig', - 'not_regex' => 'The :attribute format is invalid.', + 'not_regex' => 'Formatet på :attribute är ogiltigt.', 'numeric' => ':attribute måste vara ett nummer.', 'regex' => ':attribute har ett ogiltigt format.', 'required' => ':attribute är obligatoriskt.', diff --git a/resources/lang/tr/errors.php b/resources/lang/tr/errors.php index 7eb836b0c..50688219e 100644 --- a/resources/lang/tr/errors.php +++ b/resources/lang/tr/errors.php @@ -13,7 +13,7 @@ return [ 'email_already_confirmed' => 'E-mail halihazırda onaylanmış, giriş yapmayı dene.', 'email_confirmation_invalid' => 'Bu doğrulama tokenı daha önce kullanılmış veya geçerli değil, lütfen tekrar kayıt olmayı deneyin.', 'email_confirmation_expired' => 'Doğrulama token\'ının süresi geçmiş, yeni bir mail gönderildi.', - 'email_confirmation_awaiting' => 'The email address for the account in use needs to be confirmed', + 'email_confirmation_awaiting' => 'Kullanılan hesabın e-posta adresinin onaylanması gerekiyor', 'ldap_fail_anonymous' => 'Anonim LDAP girişi başarısız oldu', 'ldap_fail_authed' => 'Verdiğiniz bilgiler ile LDAP girişi başarısız oldu.', 'ldap_extension_not_installed' => 'LDAP PHP eklentisi yüklenmedi', @@ -83,21 +83,21 @@ return [ // Error pages '404_page_not_found' => 'Sayfa Bulunamadı', 'sorry_page_not_found' => 'Üzgünüz, aradığınız sayfa bulunamıyor.', - 'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.', + 'sorry_page_not_found_permission_warning' => 'Görüntüleyemediğiniz bu sayfanın var olduğunu düşünüyorsanız, görüntüleme izniniz olmayabilir.', 'return_home' => 'Anasayfaya dön', 'error_occurred' => 'Bir Hata Oluştu', 'app_down' => ':appName şu anda inaktif', 'back_soon' => 'En kısa zamanda aktif hale gelecek.', // API errors - 'api_no_authorization_found' => 'No authorization token found on the request', - 'api_bad_authorization_format' => 'An authorization token was found on the request but the format appeared incorrect', - 'api_user_token_not_found' => 'No matching API token was found for the provided authorization token', - 'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect', - 'api_user_no_api_permission' => 'The owner of the used API token does not have permission to make API calls', - 'api_user_token_expired' => 'The authorization token used has expired', + 'api_no_authorization_found' => 'İstekte yetkilendirme anahtarı bulunamadı', + 'api_bad_authorization_format' => 'İstekte bir yetkilendirme anahtarı bulundu, ancak biçim yanlış görünüyor', + 'api_user_token_not_found' => 'Sağlanan yetkilendirme anahtarı ile eşleşen bir API anahtarı bulunamadı', + 'api_incorrect_token_secret' => 'Kullanılan API anahtarı için sağlanan gizli anahtar doğru değil', + 'api_user_no_api_permission' => 'Kullanılan API anahtarının sahibi API çağrısı yapmak için izne sahip değil', + 'api_user_token_expired' => 'Kullanılan yetkilendirme anahtarının süresi doldu', // Settings & Maintenance - 'maintenance_test_email_failure' => 'Error thrown when sending a test email:', + 'maintenance_test_email_failure' => 'Test e-postası gönderilirken hata oluştu:', ]; diff --git a/resources/lang/tr/settings.php b/resources/lang/tr/settings.php index 1e7548afd..638796fa4 100755 --- a/resources/lang/tr/settings.php +++ b/resources/lang/tr/settings.php @@ -43,7 +43,7 @@ return [ // Color settings 'content_colors' => 'İçerik Renkleri', - 'content_colors_desc' => 'Sets colors for all elements in the page organisation hierarchy. Choosing colors with a similar brightness to the default colors is recommended for readability.', + 'content_colors_desc' => 'Sayfa organizasyon hiyerarşisi içerisindeki tüm elementler için renkleri ayarla. Renkleri benzer parlaklıkta seçmeniz okunurluk açısından önerilir.', 'bookshelf_color' => 'Raf Rengi', 'book_color' => 'Kitap Rengi', 'chapter_color' => 'Kısım Rengi', @@ -56,7 +56,7 @@ return [ 'reg_enable_toggle' => 'Kaydolmaya izin ver', 'reg_enable_desc' => 'Kayıt olmaya izin verdiğinizde kullanıcılar kendilerini uygulamaya kaydedebilecekler. Kayıt olduktan sonra kendilerine varsayılan kullanıcı rolü atanacaktır.', 'reg_default_role' => 'Kayıt olduktan sonra varsayılan kullanıcı rolü', - 'reg_enable_external_warning' => 'The option above is ignored while external LDAP or SAML authentication is active. User accounts for non-existing members will be auto-created if authentication, against the external system in use, is successful.', + 'reg_enable_external_warning' => 'Harici LDAP veya SAML kimlik doğrulaması etkinken yukarıdaki seçenek yok sayılır. Mevcut harici üyelere yönelik kimlik doğrulama başarılı olursa, mevcut olmayan üyelerin kullanıcı hesapları otomatik olarak oluşturulur.', 'reg_email_confirmation' => 'Email Doğrulama', 'reg_email_confirmation_toggle' => 'E-mail onayı gerektir', 'reg_confirm_email_desc' => 'Eğer domain kısıtlaması kullanılıyorsa o zaman email doğrulaması gereklidir ve bu seçenek yok sayılacaktır.', @@ -103,7 +103,7 @@ return [ 'role_manage_entity_permissions' => 'Bütün kitap, bölüm ve sayfa izinlerini yönet', 'role_manage_own_entity_permissions' => 'Sahip olunan kitap, bölüm ve sayfaların izinlerini yönet', 'role_manage_page_templates' => 'Sayfa şablonlarını yönet', - 'role_access_api' => 'Access system API', + 'role_access_api' => 'Sistem API\'na eriş', 'role_manage_settings' => 'Uygulama ayarlarını yönet', 'role_asset' => 'Asset Yetkileri', 'role_asset_desc' => 'Bu izinleri assetlere sistem içinden varsayılan erişimi kontrol eder. Kitaplar, bölümler ve sayfaların izinleri bu izinleri override eder.', @@ -131,7 +131,7 @@ return [ 'users_send_invite_text' => 'Bu kullanıcıya parolasını sıfırlayabilmesi için bir e-posta gönder veya şifresini sen belirle.', 'users_send_invite_option' => 'Kullanıcıya davet e-postası gönder', 'users_external_auth_id' => 'Harici Authentication ID\'si', - 'users_external_auth_id_desc' => 'This is the ID used to match this user when communicating with your external authentication system.', + 'users_external_auth_id_desc' => 'Bu ID, harici kimlik doğrulama sisteminizle iletişim kurarken bu kullanıcıyla eşleştirmek için kullanılır.', 'users_password_warning' => 'Sadece parolanızı değiştirmek istiyorsanız aşağıyı doldurunuz.', 'users_system_public' => 'Bu kullanıcı sizin uygulamanızı ziyaret eden bütün misafir kullanıcıları temsil eder. Giriş yapmak için kullanılamaz, otomatik olarak atanır.', 'users_delete' => 'Kullanıcı Sil', @@ -152,32 +152,33 @@ return [ 'users_social_disconnect' => 'Hesabın Bağlantısını Kes', 'users_social_connected' => ':socialAccount hesabı profilinize başarıyla bağlandı.', 'users_social_disconnected' => ':socialAccount hesabınızın profilinizle ilişiği başarıyla kesildi.', - 'users_api_tokens' => 'API Tokens', - 'users_api_tokens_none' => 'No API tokens have been created for this user', - 'users_api_tokens_create' => 'Create Token', - 'users_api_tokens_expires' => 'Expires', - 'users_api_tokens_docs' => 'API Documentation', + 'users_api_tokens' => 'API Anahtarları', + 'users_api_tokens_none' => 'Bu kullanıcı için oluşturulmuş API anahtarı bulunmuyor', + 'users_api_tokens_create' => 'Anahtar Oluştur', + 'users_api_tokens_expires' => 'Bitiş süresi', + 'users_api_tokens_docs' => 'API Dokümantasyonu', // API Tokens - 'user_api_token_create' => 'Create API Token', - 'user_api_token_name' => 'Name', - 'user_api_token_name_desc' => 'Give your token a readable name as a future reminder of its intended purpose.', - 'user_api_token_expiry' => 'Expiry Date', - 'user_api_token_expiry_desc' => 'Set a date at which this token expires. After this date, requests made using this token will no longer work. Leaving this field blank will set an expiry 100 years into the future.', - 'user_api_token_create_secret_message' => 'Immediately after creating this token a "Token ID"" & "Token Secret" will be generated and displayed. The secret will only be shown a single time so be sure to copy the value to somewhere safe and secure before proceeding.', - 'user_api_token_create_success' => 'API token successfully created', - 'user_api_token_update_success' => 'API token successfully updated', - 'user_api_token' => 'API Token', - 'user_api_token_id' => 'Token ID', - 'user_api_token_id_desc' => 'This is a non-editable system generated identifier for this token which will need to be provided in API requests.', - 'user_api_token_secret' => 'Token Secret', - 'user_api_token_secret_desc' => 'This is a system generated secret for this token which will need to be provided in API requests. This will only be displayed this one time so copy this value to somewhere safe and secure.', - 'user_api_token_created' => 'Token Created :timeAgo', - 'user_api_token_updated' => 'Token Updated :timeAgo', - 'user_api_token_delete' => 'Delete Token', - 'user_api_token_delete_warning' => 'This will fully delete this API token with the name \':tokenName\' from the system.', - 'user_api_token_delete_confirm' => 'Are you sure you want to delete this API token?', - 'user_api_token_delete_success' => 'API token successfully deleted', + 'user_api_token_create' => 'API Anahtarı Oluştur', + 'user_api_token_name' => 'İsim', + 'user_api_token_name_desc' => 'Anahtarınıza gelecekte ne amaçla kullanıldığını hatırlatması açısından anlamlı bir isim veriniz.', + 'user_api_token_expiry' => 'Bitiş Tarihi', + 'user_api_token_expiry_desc' => 'Bu anahtarın süresinin dolduğu bir tarih belirleyin. Bu tarihten sonra, bu anahtar kullanılarak yapılan istekler artık çalışmaz. Bu alanı boş bırakmak, bitiş tarihini 100 yıl sonrası yapar.', + 'user_api_token_create_secret_message' => 'Bu jetonu oluşturduktan hemen sonra bir "ID Anahtarı" "ve" Gizli Anahtar "oluşturulacak ve görüntülenecektir. +Gizli Anahtar yalnızca tek bir kez gösterilecektir, bu yüzden devam etmeden önce değeri güvenli bir yere kopyaladığınızdan emin olun.', + 'user_api_token_create_success' => 'API anahtarı başarıyla oluşturuldu', + 'user_api_token_update_success' => 'API anahtarı başarıyla güncellendi', + 'user_api_token' => 'API Erişim Anahtarı', + 'user_api_token_id' => 'Anahtar ID', + 'user_api_token_id_desc' => 'Bu API isteklerini karşılamak için sistem tarafından oluşturulmuş sonradan düzenlenemez bir tanımlayıcıdır.', + 'user_api_token_secret' => 'Gizli Anahtar', + 'user_api_token_secret_desc' => 'Bu, API isteklerinde sağlanması gereken anahtar için sistem tarafından oluşturulan bir gizli anahtardır. Bu yalnızca bir kez görüntülenecektir, bu nedenle bu değeri güvenli bir yere kopyalayın.', + 'user_api_token_created' => 'Anahtar :timeAgo Önce Oluşturuldu', + 'user_api_token_updated' => 'Anahtar :timeAgo Önce Güncellendi', + 'user_api_token_delete' => 'Anahtarı Sil', + 'user_api_token_delete_warning' => 'Bu işlem \':tokenName\' adındaki API anahtarını sistemden tamamen silecektir.', + 'user_api_token_delete_confirm' => 'Bu API anahtarını silmek istediğinizden emin misiniz?', + 'user_api_token_delete_success' => 'API anahtarı başarıyla silindi', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. @@ -186,7 +187,7 @@ return [ 'en' => 'English', 'ar' => 'العربية', 'cs' => 'Česky', - 'da' => 'Dansk', + 'da' => 'Danca', 'de' => 'Deutsch (Sie)', 'de_informal' => 'Deutsch (Du)', 'es' => 'Español', @@ -201,6 +202,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovence', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/uk/settings.php b/resources/lang/uk/settings.php index 882adbe29..daf8a56d5 100644 --- a/resources/lang/uk/settings.php +++ b/resources/lang/uk/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/vi/settings.php b/resources/lang/vi/settings.php index a2f499150..8886acd7b 100644 --- a/resources/lang/vi/settings.php +++ b/resources/lang/vi/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/zh_CN/settings.php b/resources/lang/zh_CN/settings.php index 43e11a442..bc01ff7ab 100755 --- a/resources/lang/zh_CN/settings.php +++ b/resources/lang/zh_CN/settings.php @@ -56,7 +56,7 @@ return [ 'reg_enable_toggle' => '启用注册', 'reg_enable_desc' => '启用注册后,用户将可以自己注册为站点用户。 注册后,他们将获得一个默认的单一用户角色。', 'reg_default_role' => '注册后的默认用户角色', - 'reg_enable_external_warning' => 'The option above is ignored while external LDAP or SAML authentication is active. User accounts for non-existing members will be auto-created if authentication, against the external system in use, is successful.', + 'reg_enable_external_warning' => '当启用外部LDAP或者SAML认证时,上面的选项会被忽略。当使用外部系统认证认证成功时,将自动创建非现有会员的用户账户。', 'reg_email_confirmation' => '邮箱确认n', 'reg_email_confirmation_toggle' => '需要电子邮件确认', 'reg_confirm_email_desc' => '如果使用域名限制,则需要Email验证,并且该值将被忽略。', @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', diff --git a/resources/lang/zh_TW/settings.php b/resources/lang/zh_TW/settings.php index 9f02dd252..02c11e5de 100644 --- a/resources/lang/zh_TW/settings.php +++ b/resources/lang/zh_TW/settings.php @@ -201,6 +201,7 @@ return [ 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', 'sv' => 'Svenska', 'tr' => 'Türkçe', 'uk' => 'Українська', From ea9e9565efab1f9cf533f01cf6ac68862bc885bf Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 5 Apr 2020 16:15:05 +0100 Subject: [PATCH 013/197] Removed bmp and tiff support from uploaded images. Fixes #1990 --- app/Http/Controllers/Controller.php | 2 +- app/Providers/AppServiceProvider.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index b9576f2fe..2e8e8ed2e 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -195,6 +195,6 @@ abstract class Controller extends BaseController */ protected function getImageValidationRules(): string { - return 'image_extension|no_double_extension|mimes:jpeg,png,gif,bmp,webp,tiff'; + return 'image_extension|no_double_extension|mimes:jpeg,png,gif,webp'; } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 3a1b4f42e..1cc3e09c2 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -34,7 +34,7 @@ class AppServiceProvider extends ServiceProvider // Custom validation methods Validator::extend('image_extension', function ($attribute, $value, $parameters, $validator) { - $validImageExtensions = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'tiff', 'webp']; + $validImageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'webp']; return in_array(strtolower($value->getClientOriginalExtension()), $validImageExtensions); }); From 5f61620cc2df5309775b946bc1bf50473c0bab2c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 5 Apr 2020 17:27:16 +0100 Subject: [PATCH 014/197] Added support for changing the draw.io instance URL - Allowed DRAWIO env option to be passed as URL to point to instance. - Updated tests to check URL gets passed to pages correctly. - Update default URL to be the default theme. For #826 --- .env.example.complete | 5 +- .../Images/DrawioImageController.php | 13 +-- resources/js/components/markdown-editor.js | 24 +++--- resources/js/components/wysiwyg-editor.js | 12 ++- resources/js/services/drawio.js | 11 ++- resources/views/pages/form.blade.php | 4 +- tests/Uploads/DrawioTest.php | 79 +++++++++++++++++++ tests/Uploads/ImageTest.php | 44 ----------- 8 files changed, 116 insertions(+), 76 deletions(-) create mode 100644 tests/Uploads/DrawioTest.php diff --git a/.env.example.complete b/.env.example.complete index 86a7351c2..472ca051b 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -238,7 +238,10 @@ DISABLE_EXTERNAL_SERVICES=false # Example: AVATAR_URL=https://seccdn.libravatar.org/avatar/${hash}?s=${size}&d=identicon AVATAR_URL= -# Enable Draw.io integration +# Enable draw.io integration +# Can simply be true/false to enable/disable the integration. +# Alternatively, It can be URL to the draw.io instance you want to use. +# For URLs, The following URL parameters should be included: embed=1&proto=json&spin=1 DRAWIO=true # Default item listing view diff --git a/app/Http/Controllers/Images/DrawioImageController.php b/app/Http/Controllers/Images/DrawioImageController.php index 3595790f7..106dfd630 100644 --- a/app/Http/Controllers/Images/DrawioImageController.php +++ b/app/Http/Controllers/Images/DrawioImageController.php @@ -4,6 +4,7 @@ namespace BookStack\Http\Controllers\Images; use BookStack\Exceptions\ImageUploadException; use BookStack\Uploads\ImageRepo; +use Exception; use Illuminate\Http\Request; use BookStack\Http\Controllers\Controller; @@ -11,10 +12,6 @@ class DrawioImageController extends Controller { protected $imageRepo; - /** - * DrawioImageController constructor. - * @param ImageRepo $imageRepo - */ public function __construct(ImageRepo $imageRepo) { $this->imageRepo = $imageRepo; @@ -24,8 +21,6 @@ class DrawioImageController extends Controller /** * Get a list of gallery images, in a list. * Can be paged and filtered by entity. - * @param Request $request - * @return \Illuminate\Http\JsonResponse */ public function list(Request $request) { @@ -40,9 +35,7 @@ class DrawioImageController extends Controller /** * Store a new gallery image in the system. - * @param Request $request - * @return Illuminate\Http\JsonResponse - * @throws \Exception + * @throws Exception */ public function create(Request $request) { @@ -66,8 +59,6 @@ class DrawioImageController extends Controller /** * Get the content of an image based64 encoded. - * @param $id - * @return \Illuminate\Http\JsonResponse|mixed */ public function getAsBase64($id) { diff --git a/resources/js/components/markdown-editor.js b/resources/js/components/markdown-editor.js index 25d6bde47..f88cb7651 100644 --- a/resources/js/components/markdown-editor.js +++ b/resources/js/components/markdown-editor.js @@ -411,17 +411,23 @@ class MarkdownEditor { }); } + getDrawioUrl() { + const drawioUrlElem = document.querySelector('[drawio-url]'); + return drawioUrlElem ? drawioUrlElem.getAttribute('drawio-url') : false; + } + // Show draw.io if enabled and handle save. actionStartDrawing() { - if (document.querySelector('[drawio-enabled]').getAttribute('drawio-enabled') !== 'true') return; - let cursorPos = this.cm.getCursor('from'); + const url = this.getDrawioUrl(); + if (!url) return; - DrawIO.show(() => { + const cursorPos = this.cm.getCursor('from'); + + DrawIO.show(url,() => { return Promise.resolve(''); }, (pngData) => { - // let id = "image-" + Math.random().toString(16).slice(2); - // let loadingImage = window.baseUrl('/loading.gif'); - let data = { + + const data = { image: pngData, uploaded_to: Number(document.getElementById('page-editor').getAttribute('page-id')) }; @@ -445,15 +451,15 @@ class MarkdownEditor { // Show draw.io if enabled and handle save. actionEditDrawing(imgContainer) { - const drawingDisabled = document.querySelector('[drawio-enabled]').getAttribute('drawio-enabled') !== 'true'; - if (drawingDisabled) { + const drawioUrl = this.getDrawioUrl(); + if (!drawioUrl) { return; } const cursorPos = this.cm.getCursor('from'); const drawingId = imgContainer.getAttribute('drawio-diagram'); - DrawIO.show(() => { + DrawIO.show(drawioUrl, () => { return DrawIO.load(drawingId); }, (pngData) => { diff --git a/resources/js/components/wysiwyg-editor.js b/resources/js/components/wysiwyg-editor.js index 7818db260..daacc7479 100644 --- a/resources/js/components/wysiwyg-editor.js +++ b/resources/js/components/wysiwyg-editor.js @@ -238,7 +238,7 @@ function codePlugin() { }); } -function drawIoPlugin() { +function drawIoPlugin(drawioUrl) { let pageEditor = null; let currentNode = null; @@ -266,7 +266,7 @@ function drawIoPlugin() { function showDrawingEditor(mceEditor, selectedNode = null) { pageEditor = mceEditor; currentNode = selectedNode; - DrawIO.show(drawingInit, updateContent); + DrawIO.show(drawioUrl, drawingInit, updateContent); } async function updateContent(pngData) { @@ -423,10 +423,14 @@ class WysiwygEditor { loadPlugins() { codePlugin(); customHrPlugin(); - if (document.querySelector('[drawio-enabled]').getAttribute('drawio-enabled') === 'true') { - drawIoPlugin(); + + const drawioUrlElem = document.querySelector('[drawio-url]'); + if (drawioUrlElem) { + const url = drawioUrlElem.getAttribute('drawio-url'); + drawIoPlugin(url); this.plugins += ' drawio'; } + if (this.textDirection === 'rtl') { this.plugins += ' directionality' } diff --git a/resources/js/services/drawio.js b/resources/js/services/drawio.js index a570737d1..17e57cd6b 100644 --- a/resources/js/services/drawio.js +++ b/resources/js/services/drawio.js @@ -1,22 +1,21 @@ - -const drawIoUrl = 'https://www.draw.io/?embed=1&ui=atlas&spin=1&proto=json'; let iFrame = null; let onInit, onSave; /** * Show the draw.io editor. - * @param onInitCallback - Must return a promise with the xml to load for the editor. - * @param onSaveCallback - Is called with the drawing data on save. + * @param {String} drawioUrl + * @param {Function} onInitCallback - Must return a promise with the xml to load for the editor. + * @param {Function} onSaveCallback - Is called with the drawing data on save. */ -function show(onInitCallback, onSaveCallback) { +function show(drawioUrl, onInitCallback, onSaveCallback) { onInit = onInitCallback; onSave = onSaveCallback; iFrame = document.createElement('iframe'); iFrame.setAttribute('frameborder', '0'); window.addEventListener('message', drawReceive); - iFrame.setAttribute('src', drawIoUrl); + iFrame.setAttribute('src', drawioUrl); iFrame.setAttribute('class', 'fullscreen'); iFrame.style.backgroundColor = '#FFFFFF'; document.body.appendChild(iFrame); diff --git a/resources/views/pages/form.blade.php b/resources/views/pages/form.blade.php index ffc286c2c..3c2b4f0b0 100644 --- a/resources/views/pages/form.blade.php +++ b/resources/views/pages/form.blade.php @@ -1,6 +1,8 @@
asAdmin(); + $imageName = 'first-image.png'; + + $this->uploadImage($imageName, $page->id); + $image = Image::first(); + $image->type = 'drawio'; + $image->save(); + + $imageGet = $this->getJson("/images/drawio/base64/{$image->id}"); + $imageGet->assertJson([ + 'content' => 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII=' + ]); + } + + public function test_drawing_base64_upload() + { + $page = Page::first(); + $editor = $this->getEditor(); + $this->actingAs($editor); + + $upload = $this->postJson('images/drawio', [ + 'uploaded_to' => $page->id, + 'image' => 'image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII=' + ]); + + $upload->assertStatus(200); + $upload->assertJson([ + 'type' => 'drawio', + 'uploaded_to' => $page->id, + 'created_by' => $editor->id, + 'updated_by' => $editor->id, + ]); + + $image = Image::where('type', '=', 'drawio')->first(); + $this->assertTrue(file_exists(public_path($image->path)), 'Uploaded image not found at path: '. public_path($image->path)); + + $testImageData = file_get_contents($this->getTestImageFilePath()); + $uploadedImageData = file_get_contents(public_path($image->path)); + $this->assertTrue($testImageData === $uploadedImageData, "Uploaded image file data does not match our test image as expected"); + } + + public function test_drawio_url_can_be_configured() + { + config()->set('services.drawio', 'http://cats.com?dog=tree'); + $page = Page::first(); + $editor = $this->getEditor(); + + $resp = $this->actingAs($editor)->get($page->getUrl('/edit')); + $resp->assertSee('drawio-url="http://cats.com?dog=tree"'); + } + + public function test_drawio_url_can_be_disabled() + { + config()->set('services.drawio', true); + $page = Page::first(); + $editor = $this->getEditor(); + + $resp = $this->actingAs($editor)->get($page->getUrl('/edit')); + $resp->assertSee('drawio-url="https://www.draw.io/?embed=1&proto=json&spin=1"'); + + config()->set('services.drawio', false); + $resp = $this->actingAs($editor)->get($page->getUrl('/edit')); + $resp->assertDontSee('drawio-url'); + } + +} \ No newline at end of file diff --git a/tests/Uploads/ImageTest.php b/tests/Uploads/ImageTest.php index 3f6c021a7..416927ac9 100644 --- a/tests/Uploads/ImageTest.php +++ b/tests/Uploads/ImageTest.php @@ -278,50 +278,6 @@ class ImageTest extends TestCase $this->assertFalse(file_exists(public_path($relPath)), 'Uploaded image has not been deleted as expected'); } - public function testBase64Get() - { - $page = Page::first(); - $this->asAdmin(); - $imageName = 'first-image.png'; - - $this->uploadImage($imageName, $page->id); - $image = Image::first(); - $image->type = 'drawio'; - $image->save(); - - $imageGet = $this->getJson("/images/drawio/base64/{$image->id}"); - $imageGet->assertJson([ - 'content' => 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII=' - ]); - } - - public function test_drawing_base64_upload() - { - $page = Page::first(); - $editor = $this->getEditor(); - $this->actingAs($editor); - - $upload = $this->postJson('images/drawio', [ - 'uploaded_to' => $page->id, - 'image' => 'image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII=' - ]); - - $upload->assertStatus(200); - $upload->assertJson([ - 'type' => 'drawio', - 'uploaded_to' => $page->id, - 'created_by' => $editor->id, - 'updated_by' => $editor->id, - ]); - - $image = Image::where('type', '=', 'drawio')->first(); - $this->assertTrue(file_exists(public_path($image->path)), 'Uploaded image not found at path: '. public_path($image->path)); - - $testImageData = file_get_contents($this->getTestImageFilePath()); - $uploadedImageData = file_get_contents(public_path($image->path)); - $this->assertTrue($testImageData === $uploadedImageData, "Uploaded image file data does not match our test image as expected"); - } - protected function getTestProfileImage() { $imageName = 'profile.png'; From 02f7ffe53ceca1f83676473cf741b47401814b34 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 5 Apr 2020 18:05:51 +0100 Subject: [PATCH 015/197] Removed overflow hidden from all lists - Was causing ol list numbers to be cut off. Fixes #1978 --- resources/sass/_text.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/sass/_text.scss b/resources/sass/_text.scss index 00fc772cc..8d2759b91 100644 --- a/resources/sass/_text.scss +++ b/resources/sass/_text.scss @@ -262,7 +262,6 @@ span.highlight { * Lists */ ul, ol { - overflow: hidden; p { margin: 0; } From 642db1387ef511046fb60380dd65446d8b43509d Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 5 Apr 2020 21:55:31 +0100 Subject: [PATCH 016/197] Updated wysiwyg code-block insert flow to be mouseless - Can now save a code block with Ctrl+Enter. - Codemirror will be in focus on popup show. - TinyMCE will get back focus on code save. For #1972 --- resources/js/components/wysiwyg-editor.js | 18 +++++++++++------- resources/js/vues/code-editor.js | 1 + .../views/components/code-editor.blade.php | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/resources/js/components/wysiwyg-editor.js b/resources/js/components/wysiwyg-editor.js index daacc7479..1fd859de4 100644 --- a/resources/js/components/wysiwyg-editor.js +++ b/resources/js/components/wysiwyg-editor.js @@ -139,19 +139,21 @@ function codePlugin() { } function showPopup(editor) { - let selectedNode = editor.selection.getNode(); + const selectedNode = editor.selection.getNode(); if (!elemIsCodeBlock(selectedNode)) { - let providedCode = editor.selection.getNode().textContent; + const providedCode = editor.selection.getNode().textContent; window.vues['code-editor'].open(providedCode, '', (code, lang) => { - let wrap = document.createElement('div'); + const wrap = document.createElement('div'); wrap.innerHTML = `
`; wrap.querySelector('code').innerText = code; editor.formatter.toggle('pre'); - let node = editor.selection.getNode(); + const node = editor.selection.getNode(); editor.dom.setHTML(node, wrap.querySelector('pre').innerHTML); editor.fire('SetContent'); + + editor.focus() }); return; } @@ -160,15 +162,17 @@ function codePlugin() { let currentCode = selectedNode.querySelector('textarea').textContent; window.vues['code-editor'].open(currentCode, lang, (code, lang) => { - let editorElem = selectedNode.querySelector('.CodeMirror'); - let cmInstance = editorElem.CodeMirror; + const editorElem = selectedNode.querySelector('.CodeMirror'); + const cmInstance = editorElem.CodeMirror; if (cmInstance) { Code.setContent(cmInstance, code); Code.setMode(cmInstance, lang, code); } - let textArea = selectedNode.querySelector('textarea'); + const textArea = selectedNode.querySelector('textarea'); if (textArea) textArea.textContent = code; selectedNode.setAttribute('data-lang', lang); + + editor.focus() }); } diff --git a/resources/js/vues/code-editor.js b/resources/js/vues/code-editor.js index 48b4e1766..f888e6227 100644 --- a/resources/js/vues/code-editor.js +++ b/resources/js/vues/code-editor.js @@ -5,6 +5,7 @@ const methods = { if (!this.editor) this.editor = codeLib.popupEditor(this.$refs.editor, this.language); this.$refs.overlay.components.overlay.show(() => { codeLib.updateLayout(this.editor); + this.editor.focus(); }); }, hide() { diff --git a/resources/views/components/code-editor.blade.php b/resources/views/components/code-editor.blade.php index d6046664e..15f6ae252 100644 --- a/resources/views/components/code-editor.blade.php +++ b/resources/views/components/code-editor.blade.php @@ -1,6 +1,6 @@
- @endif + @if(count($bookParentShelves) > 0) +
+
{{ trans('entities.shelves_long') }}
+ @include('partials.entity-list', ['entities' => $bookParentShelves, 'style' => 'compact']) +
+ @endif + @if(count($activity) > 0)
{{ trans('entities.recent_activity') }}
diff --git a/tests/Entity/BookShelfTest.php b/tests/Entity/BookShelfTest.php index 8f41e83ab..abee4d34a 100644 --- a/tests/Entity/BookShelfTest.php +++ b/tests/Entity/BookShelfTest.php @@ -284,7 +284,7 @@ class BookShelfTest extends TestCase $newBook = Book::query()->orderBy('id', 'desc')->first(); $resp = $this->asEditor()->get($newBook->getUrl()); - $resp->assertSee($shelfInfo['name']); + $resp->assertElementContains('.tri-layout-left-contents', $shelfInfo['name']); // Remove shelf $this->delete($shelf->getUrl()); From 053cbbd5b6cd98788ae4f0c56fc220ae6b020736 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 10 Apr 2020 12:49:16 +0100 Subject: [PATCH 020/197] Updated view-change endpoints to be clearer, separated books and shelf - Separated books-list and shelf-show view types to be saved separately. During review of #1755 --- app/Http/Controllers/BookshelfController.php | 2 +- app/Http/Controllers/UserController.php | 65 +++++-------------- resources/views/books/index.blade.php | 2 +- resources/views/common/home-book.blade.php | 2 +- resources/views/common/home-shelves.blade.php | 2 +- resources/views/shelves/index.blade.php | 2 +- resources/views/shelves/show.blade.php | 2 +- routes/web.php | 3 +- tests/User/UserProfileTest.php | 35 ++++++++-- 9 files changed, 54 insertions(+), 61 deletions(-) diff --git a/app/Http/Controllers/BookshelfController.php b/app/Http/Controllers/BookshelfController.php index c46cac277..f2cc11c7b 100644 --- a/app/Http/Controllers/BookshelfController.php +++ b/app/Http/Controllers/BookshelfController.php @@ -103,11 +103,11 @@ class BookshelfController extends Controller public function show(string $slug) { $shelf = $this->bookshelfRepo->getBySlug($slug); - $view = setting()->getForCurrentUser('books_view_type', config('app.views.books')); $this->checkOwnablePermission('book-view', $shelf); Views::add($shelf); $this->entityContextManager->setShelfContext($shelf->id); + $view = setting()->getForCurrentUser('bookshelf_view_type', config('app.views.books')); $this->setPageTitle($shelf->getShortName()); return view('shelves.show', [ diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 55a4610bc..43cbad1fb 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -7,7 +7,6 @@ use BookStack\Auth\UserRepo; use BookStack\Exceptions\UserUpdateException; use BookStack\Uploads\ImageRepo; use Illuminate\Http\Request; -use Illuminate\Http\Response; use Illuminate\Support\Str; class UserController extends Controller @@ -20,10 +19,6 @@ class UserController extends Controller /** * UserController constructor. - * @param User $user - * @param UserRepo $userRepo - * @param UserInviteService $inviteService - * @param ImageRepo $imageRepo */ public function __construct(User $user, UserRepo $userRepo, UserInviteService $inviteService, ImageRepo $imageRepo) { @@ -36,8 +31,6 @@ class UserController extends Controller /** * Display a listing of the users. - * @param Request $request - * @return Response */ public function index(Request $request) { @@ -55,7 +48,6 @@ class UserController extends Controller /** * Show the form for creating a new user. - * @return Response */ public function create() { @@ -67,9 +59,8 @@ class UserController extends Controller /** * Store a newly created user in storage. - * @param Request $request - * @return Response * @throws UserUpdateException + * @throws \Illuminate\Validation\ValidationException */ public function store(Request $request) { @@ -138,13 +129,11 @@ class UserController extends Controller /** * Update the specified user in storage. - * @param Request $request - * @param int $id - * @return Response * @throws UserUpdateException * @throws \BookStack\Exceptions\ImageUploadException + * @throws \Illuminate\Validation\ValidationException */ - public function update(Request $request, $id) + public function update(Request $request, int $id) { $this->preventAccessInDemoMode(); $this->checkPermissionOrCurrentUser('users-manage', $id); @@ -212,10 +201,8 @@ class UserController extends Controller /** * Show the user delete page. - * @param int $id - * @return \Illuminate\View\View */ - public function delete($id) + public function delete(int $id) { $this->checkPermissionOrCurrentUser('users-manage', $id); @@ -226,11 +213,9 @@ class UserController extends Controller /** * Remove the specified user from storage. - * @param int $id - * @return Response * @throws \Exception */ - public function destroy($id) + public function destroy(int $id) { $this->preventAccessInDemoMode(); $this->checkPermissionOrCurrentUser('users-manage', $id); @@ -255,8 +240,6 @@ class UserController extends Controller /** * Show the user profile page - * @param $id - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function showProfilePage($id) { @@ -276,34 +259,32 @@ class UserController extends Controller /** * Update the user's preferred book-list display setting. - * @param Request $request - * @param $id - * @return \Illuminate\Http\RedirectResponse */ - public function switchBookView(Request $request, $id) + public function switchBooksView(Request $request, int $id) { return $this->switchViewType($id, $request, 'books'); } /** * Update the user's preferred shelf-list display setting. - * @param Request $request - * @param $id - * @return \Illuminate\Http\RedirectResponse */ - public function switchShelfView(Request $request, $id) + public function switchShelvesView(Request $request, int $id) { return $this->switchViewType($id, $request, 'bookshelves'); } /** - * For a type of list, switch with stored view type for a user. - * @param integer $userId - * @param Request $request - * @param string $listName - * @return \Illuminate\Http\RedirectResponse + * Update the user's preferred shelf-view book list display setting. */ - protected function switchViewType($userId, Request $request, string $listName) + public function switchShelfView(Request $request, int $id) + { + return $this->switchViewType($id, $request, 'bookshelf'); + } + + /** + * For a type of list, switch with stored view type for a user. + */ + protected function switchViewType(int $userId, Request $request, string $listName) { $this->checkPermissionOrCurrentUser('users-manage', $userId); @@ -321,10 +302,6 @@ class UserController extends Controller /** * Change the stored sort type for a particular view. - * @param Request $request - * @param string $id - * @param string $type - * @return \Illuminate\Http\RedirectResponse */ public function changeSort(Request $request, string $id, string $type) { @@ -337,10 +314,6 @@ class UserController extends Controller /** * Update the stored section expansion preference for the given user. - * @param Request $request - * @param string $id - * @param string $key - * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response */ public function updateExpansionPreference(Request $request, string $id, string $key) { @@ -359,10 +332,6 @@ class UserController extends Controller /** * Changed the stored preference for a list sort order. - * @param int $userId - * @param Request $request - * @param string $listName - * @return \Illuminate\Http\RedirectResponse */ protected function changeListSort(int $userId, Request $request, string $listName) { diff --git a/resources/views/books/index.blade.php b/resources/views/books/index.blade.php index b9bd987a9..f3c3ee34b 100644 --- a/resources/views/books/index.blade.php +++ b/resources/views/books/index.blade.php @@ -43,7 +43,7 @@ @endif - @include('partials.view-toggle', ['view' => $view, 'type' => 'book']) + @include('partials.view-toggle', ['view' => $view, 'type' => 'books'])
diff --git a/resources/views/common/home-book.blade.php b/resources/views/common/home-book.blade.php index 7644eeb88..8caae814a 100644 --- a/resources/views/common/home-book.blade.php +++ b/resources/views/common/home-book.blade.php @@ -12,7 +12,7 @@
{{ trans('common.actions') }}
- @include('partials.view-toggle', ['view' => $view, 'type' => 'book']) + @include('partials.view-toggle', ['view' => $view, 'type' => 'books']) @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
diff --git a/resources/views/common/home-shelves.blade.php b/resources/views/common/home-shelves.blade.php index a9c585893..bac6fa154 100644 --- a/resources/views/common/home-shelves.blade.php +++ b/resources/views/common/home-shelves.blade.php @@ -12,7 +12,7 @@
{{ trans('common.actions') }}
- @include('partials.view-toggle', ['view' => $view, 'type' => 'shelf']) + @include('partials.view-toggle', ['view' => $view, 'type' => 'shelves']) @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
diff --git a/resources/views/shelves/index.blade.php b/resources/views/shelves/index.blade.php index 98f97f133..56b76f96f 100644 --- a/resources/views/shelves/index.blade.php +++ b/resources/views/shelves/index.blade.php @@ -15,7 +15,7 @@ {{ trans('entities.shelves_new_action') }} @endif - @include('partials.view-toggle', ['view' => $view, 'type' => 'shelf']) + @include('partials.view-toggle', ['view' => $view, 'type' => 'shelves'])
diff --git a/resources/views/shelves/show.blade.php b/resources/views/shelves/show.blade.php index 56df61c91..6fee6f45d 100644 --- a/resources/views/shelves/show.blade.php +++ b/resources/views/shelves/show.blade.php @@ -95,7 +95,7 @@ @endif - @include('partials.view-toggle', ['view' => $view, 'type' => 'book']) + @include('partials.view-toggle', ['view' => $view, 'type' => 'shelf'])
diff --git a/routes/web.php b/routes/web.php index 90261e1ac..4dfccdf36 100644 --- a/routes/web.php +++ b/routes/web.php @@ -178,7 +178,8 @@ Route::group(['middleware' => 'auth'], function () { Route::get('/users', 'UserController@index'); Route::get('/users/create', 'UserController@create'); Route::get('/users/{id}/delete', 'UserController@delete'); - Route::patch('/users/{id}/switch-book-view', 'UserController@switchBookView'); + Route::patch('/users/{id}/switch-books-view', 'UserController@switchBooksView'); + Route::patch('/users/{id}/switch-shelves-view', 'UserController@switchShelvesView'); Route::patch('/users/{id}/switch-shelf-view', 'UserController@switchShelfView'); Route::patch('/users/{id}/change-sort/{type}', 'UserController@changeSort'); Route::patch('/users/{id}/update-expansion-preference/{key}', 'UserController@updateExpansionPreference'); diff --git a/tests/User/UserProfileTest.php b/tests/User/UserProfileTest.php index 979064baa..0a3a1a6b2 100644 --- a/tests/User/UserProfileTest.php +++ b/tests/User/UserProfileTest.php @@ -1,5 +1,8 @@ user = \BookStack\Auth\User::all()->last(); + $this->user = User::all()->last(); } public function test_profile_page_shows_name() @@ -57,8 +60,8 @@ class UserProfileTest extends BrowserKitTest $newUser = $this->getNewBlankUser(); $this->actingAs($newUser); $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); - \Activity::add($entities['book'], 'book_update', $entities['book']->id); - \Activity::add($entities['page'], 'page_create', $entities['book']->id); + Activity::add($entities['book'], 'book_update', $entities['book']->id); + Activity::add($entities['page'], 'page_create', $entities['book']->id); $this->asAdmin()->visit('/user/' . $newUser->id) ->seeInElement('#recent-user-activity', 'updated book') @@ -71,8 +74,8 @@ class UserProfileTest extends BrowserKitTest $newUser = $this->getNewBlankUser(); $this->actingAs($newUser); $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); - \Activity::add($entities['book'], 'book_update', $entities['book']->id); - \Activity::add($entities['page'], 'page_create', $entities['book']->id); + Activity::add($entities['book'], 'book_update', $entities['book']->id); + Activity::add($entities['page'], 'page_create', $entities['book']->id); $this->asAdmin()->visit('/')->clickInElement('#recent-activity', $newUser->name) ->seePageIs('/user/' . $newUser->id) @@ -89,7 +92,7 @@ class UserProfileTest extends BrowserKitTest public function test_guest_profile_cannot_be_deleted() { - $guestUser = \BookStack\Auth\User::getDefault(); + $guestUser = User::getDefault(); $this->asAdmin()->visit('/settings/users/' . $guestUser->id . '/delete') ->see('Delete User')->see('Guest') ->press('Confirm') @@ -118,4 +121,24 @@ class UserProfileTest extends BrowserKitTest ->pageHasElement('.featured-image-container'); } + public function test_shelf_view_type_change() + { + $editor = $this->getEditor(); + $shelf = Bookshelf::query()->first(); + setting()->putUser($editor, 'bookshelf_view_type', 'list'); + + $this->actingAs($editor)->visit($shelf->getUrl()) + ->pageNotHasElement('.featured-image-container') + ->pageHasElement('.content-wrap .entity-list-item') + ->see('Grid View'); + + $req = $this->patch("/settings/users/{$editor->id}/switch-shelf-view", ['view_type' => 'grid']); + $req->assertRedirectedTo($shelf->getUrl()); + + $this->actingAs($editor)->visit($shelf->getUrl()) + ->pageHasElement('.featured-image-container') + ->pageNotHasElement('.content-wrap .entity-list-item') + ->see('List View'); + } + } From ba1be9d710fe5d7fc242f2a3a706265b49f83210 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 10 Apr 2020 13:38:08 +0100 Subject: [PATCH 021/197] Updated password reset process not to indicate if email exists - Intended to prevent enumeration to check if a user exists. - Updated messages on both the reqest-reset and set-password elements. - Also updated notification auto-hide to be dynamic based upon the amount of words within the notification. - Added tests to cover. For #2016 --- .../Auth/ForgotPasswordController.php | 6 +-- .../Auth/ResetPasswordController.php | 21 ++++++++++ resources/js/components/notification.js | 6 ++- resources/lang/en/auth.php | 2 +- resources/lang/en/passwords.php | 2 +- tests/Auth/AuthTest.php | 39 +++++++++++++++---- 6 files changed, 63 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index a60fcc1c9..fadac641e 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -5,7 +5,7 @@ namespace BookStack\Http\Controllers\Auth; use BookStack\Http\Controllers\Controller; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; use Illuminate\Http\Request; -use Password; +use Illuminate\Support\Facades\Password; class ForgotPasswordController extends Controller { @@ -52,8 +52,8 @@ class ForgotPasswordController extends Controller $request->only('email') ); - if ($response === Password::RESET_LINK_SENT) { - $message = trans('auth.reset_password_sent_success', ['email' => $request->get('email')]); + if ($response === Password::RESET_LINK_SENT || $response === Password::INVALID_USER) { + $message = trans('auth.reset_password_sent', ['email' => $request->get('email')]); $this->showSuccessNotification($message); return back()->with('status', trans($response)); } diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 214647cd5..efdf00159 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -5,6 +5,7 @@ namespace BookStack\Http\Controllers\Auth; use BookStack\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ResetsPasswords; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Password; class ResetPasswordController extends Controller { @@ -49,4 +50,24 @@ class ResetPasswordController extends Controller return redirect($this->redirectPath()) ->with('status', trans($response)); } + + /** + * Get the response for a failed password reset. + * + * @param \Illuminate\Http\Request $request + * @param string $response + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + */ + protected function sendResetFailedResponse(Request $request, $response) + { + // We show invalid users as invalid tokens as to not leak what + // users may exist in the system. + if ($response === Password::INVALID_USER) { + $response = Password::INVALID_TOKEN; + } + + return redirect()->back() + ->withInput($request->only('email')) + ->withErrors(['email' => trans($response)]); + } } diff --git a/resources/js/components/notification.js b/resources/js/components/notification.js index f7edb08aa..35bab4ea6 100644 --- a/resources/js/components/notification.js +++ b/resources/js/components/notification.js @@ -28,7 +28,11 @@ class Notification { this.elem.classList.add('showing'); }, 1); - if (this.autohide) setTimeout(this.hide.bind(this), 2000); + if (this.autohide) { + const words = textToShow.split(' ').length; + const timeToShow = Math.max(2000, 1000 + (250 * words)); + setTimeout(this.hide.bind(this), timeToShow); + } } hide() { diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php index 6961e049b..d64fce93a 100644 --- a/resources/lang/en/auth.php +++ b/resources/lang/en/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Reset Password', 'reset_password_send_instructions' => 'Enter your email below and you will be sent an email with a password reset link.', 'reset_password_send_button' => 'Send Reset Link', - 'reset_password_sent_success' => 'A password reset link has been sent to :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Your password has been successfully reset.', 'email_reset_subject' => 'Reset your :appName password', 'email_reset_text' => 'You are receiving this email because we received a password reset request for your account.', diff --git a/resources/lang/en/passwords.php b/resources/lang/en/passwords.php index f41ca7868..b408f3c2f 100644 --- a/resources/lang/en/passwords.php +++ b/resources/lang/en/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Passwords must be at least eight characters and match the confirmation.', 'user' => "We can't find a user with that e-mail address.", - 'token' => 'This password reset token is invalid.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'We have e-mailed your password reset link!', 'reset' => 'Your password has been reset!', diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php index cb27de961..40bcda713 100644 --- a/tests/Auth/AuthTest.php +++ b/tests/Auth/AuthTest.php @@ -1,9 +1,13 @@ press('Resend Confirmation Email'); // Get confirmation and confirm notification matches - $emailConfirmation = \DB::table('email_confirmations')->where('user_id', '=', $dbUser->id)->first(); + $emailConfirmation = DB::table('email_confirmations')->where('user_id', '=', $dbUser->id)->first(); Notification::assertSentTo($dbUser, ConfirmEmail::class, function($notification, $channels) use ($emailConfirmation) { return $notification->token === $emailConfirmation->token; }); @@ -257,7 +261,7 @@ class AuthTest extends BrowserKitTest ->seePageIs('/settings/users'); $userPassword = User::find($user->id)->password; - $this->assertTrue(\Hash::check('newpassword', $userPassword)); + $this->assertTrue(Hash::check('newpassword', $userPassword)); } public function test_user_deletion() @@ -276,7 +280,7 @@ class AuthTest extends BrowserKitTest public function test_user_cannot_be_deleted_if_last_admin() { - $adminRole = \BookStack\Auth\Role::getRole('admin'); + $adminRole = Role::getRole('admin'); // Delete all but one admin user if there are more than one $adminUsers = $adminRole->users; @@ -309,14 +313,13 @@ class AuthTest extends BrowserKitTest public function test_reset_password_flow() { - Notification::fake(); $this->visit('/login')->click('Forgot Password?') ->seePageIs('/password/email') ->type('admin@admin.com', 'email') ->press('Send Reset Link') - ->see('A password reset link has been sent to admin@admin.com'); + ->see('A password reset link will be sent to admin@admin.com if that email address is found in the system.'); $this->seeInDatabase('password_resets', [ 'email' => 'admin@admin.com' @@ -324,8 +327,8 @@ class AuthTest extends BrowserKitTest $user = User::where('email', '=', 'admin@admin.com')->first(); - Notification::assertSentTo($user, \BookStack\Notifications\ResetPassword::class); - $n = Notification::sent($user, \BookStack\Notifications\ResetPassword::class); + Notification::assertSentTo($user, ResetPassword::class); + $n = Notification::sent($user, ResetPassword::class); $this->visit('/password/reset/' . $n->first()->token) ->see('Reset Password') @@ -337,6 +340,28 @@ class AuthTest extends BrowserKitTest ->see('Your password has been successfully reset'); } + public function test_reset_password_flow_shows_success_message_even_if_wrong_password_to_prevent_user_discovery() + { + $this->visit('/login')->click('Forgot Password?') + ->seePageIs('/password/email') + ->type('barry@admin.com', 'email') + ->press('Send Reset Link') + ->see('A password reset link will be sent to barry@admin.com if that email address is found in the system.') + ->dontSee('We can\'t find a user'); + + + $this->visit('/password/reset/arandometokenvalue') + ->see('Reset Password') + ->submitForm('Reset Password', [ + 'email' => 'barry@admin.com', + 'password' => 'randompass', + 'password_confirmation' => 'randompass' + ])->followRedirects() + ->seePageIs('/password/reset/arandometokenvalue') + ->dontSee('We can\'t find a user') + ->see('The password reset token is invalid for this email address.'); + } + public function test_reset_password_page_shows_sign_links() { $this->setSettings(['registration-enabled' => 'true']); From 29705a25cee61d9c063e0f102cd018557aec5abd Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 10 Apr 2020 15:19:18 +0100 Subject: [PATCH 022/197] Reviewed and added testing for BookShelf API implementation - Tweaked how books are passed on update to prevent unassignment if parameter is not provided. - Added books to validation so they show in docs. - Added request/response examples. - Added tests to cover. - Added child book info to shelf info. Review of #1908 --- app/Auth/User.php | 5 +- app/Entities/Book.php | 2 +- app/Entities/Bookshelf.php | 2 + app/Entities/Repos/BookshelfRepo.php | 8 +- .../Api/BookshelfApiController.php | 27 ++-- dev/api/requests/shelves-create.json | 5 + dev/api/requests/shelves-update.json | 5 + dev/api/responses/books-read.json | 4 - dev/api/responses/shelves-create.json | 10 ++ dev/api/responses/shelves-list.json | 38 +++++ dev/api/responses/shelves-read.json | 60 ++++++++ dev/api/responses/shelves-update.json | 11 ++ tests/Api/ShelvesApiTest.php | 136 ++++++++++++++++++ 13 files changed, 296 insertions(+), 17 deletions(-) create mode 100644 dev/api/requests/shelves-create.json create mode 100644 dev/api/requests/shelves-update.json create mode 100644 dev/api/responses/shelves-create.json create mode 100644 dev/api/responses/shelves-list.json create mode 100644 dev/api/responses/shelves-read.json create mode 100644 dev/api/responses/shelves-update.json create mode 100644 tests/Api/ShelvesApiTest.php diff --git a/app/Auth/User.php b/app/Auth/User.php index 28fb9c7fc..a581d9993 100644 --- a/app/Auth/User.php +++ b/app/Auth/User.php @@ -47,7 +47,10 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon * The attributes excluded from the model's JSON form. * @var array */ - protected $hidden = ['password', 'remember_token', 'system_name', 'email_confirmed', 'external_auth_id', 'email']; + protected $hidden = [ + 'password', 'remember_token', 'system_name', 'email_confirmed', 'external_auth_id', 'email', + 'created_at', 'updated_at', + ]; /** * This holds the user's permissions when loaded. diff --git a/app/Entities/Book.php b/app/Entities/Book.php index df0d99228..38b7d4a8c 100644 --- a/app/Entities/Book.php +++ b/app/Entities/Book.php @@ -19,7 +19,7 @@ class Book extends Entity implements HasCoverImage public $searchFactor = 2; protected $fillable = ['name', 'description']; - protected $hidden = ['restricted']; + protected $hidden = ['restricted', 'pivot']; /** * Get the url for this book. diff --git a/app/Entities/Bookshelf.php b/app/Entities/Bookshelf.php index 62c7e2fe4..c7ba840e0 100644 --- a/app/Entities/Bookshelf.php +++ b/app/Entities/Bookshelf.php @@ -12,6 +12,8 @@ class Bookshelf extends Entity implements HasCoverImage protected $fillable = ['name', 'description', 'image_id']; + protected $hidden = ['restricted']; + /** * Get the books in this shelf. * Should not be used directly since does not take into account permissions. diff --git a/app/Entities/Repos/BookshelfRepo.php b/app/Entities/Repos/BookshelfRepo.php index 25fa97dae..876f56e10 100644 --- a/app/Entities/Repos/BookshelfRepo.php +++ b/app/Entities/Repos/BookshelfRepo.php @@ -91,10 +91,14 @@ class BookshelfRepo /** * Create a new shelf in the system. */ - public function update(Bookshelf $shelf, array $input, array $bookIds): Bookshelf + public function update(Bookshelf $shelf, array $input, ?array $bookIds): Bookshelf { $this->baseRepo->update($shelf, $input); - $this->updateBooks($shelf, $bookIds); + + if (!is_null($bookIds)) { + $this->updateBooks($shelf, $bookIds); + } + return $shelf; } diff --git a/app/Http/Controllers/Api/BookshelfApiController.php b/app/Http/Controllers/Api/BookshelfApiController.php index e6379fdec..14b5e053b 100644 --- a/app/Http/Controllers/Api/BookshelfApiController.php +++ b/app/Http/Controllers/Api/BookshelfApiController.php @@ -4,10 +4,10 @@ use BookStack\Facades\Activity; use BookStack\Entities\Repos\BookshelfRepo; use BookStack\Entities\Bookshelf; use Exception; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Http\Request; use Illuminate\Validation\ValidationException; - class BookshelfApiController extends ApiController { @@ -20,10 +20,12 @@ class BookshelfApiController extends ApiController 'create' => [ 'name' => 'required|string|max:255', 'description' => 'string|max:1000', + 'books' => 'array', ], 'update' => [ 'name' => 'string|min:1|max:255', 'description' => 'string|max:1000', + 'books' => 'array', ], ]; @@ -49,6 +51,8 @@ class BookshelfApiController extends ApiController /** * Create a new shelf in the system. + * An array of books IDs can be provided in the request. These + * will be added to the shelf in the same order as provided. * @throws ValidationException */ public function create(Request $request) @@ -57,10 +61,9 @@ class BookshelfApiController extends ApiController $requestData = $this->validate($request, $this->rules['create']); $bookIds = $request->get('books', []); + $shelf = $this->bookshelfRepo->create($requestData, $bookIds); - $shelf = $this->bookshelfRepo->create($requestData,$bookIds); Activity::add($shelf, 'bookshelf_create', $shelf->id); - return response()->json($shelf); } @@ -69,12 +72,20 @@ class BookshelfApiController extends ApiController */ public function read(string $id) { - $shelf = Bookshelf::visible()->with(['tags', 'cover', 'createdBy', 'updatedBy'])->findOrFail($id); + $shelf = Bookshelf::visible()->with([ + 'tags', 'cover', 'createdBy', 'updatedBy', + 'books' => function (BelongsToMany $query) { + $query->visible()->get(['id', 'name', 'slug']); + } + ])->findOrFail($id); return response()->json($shelf); } /** * Update the details of a single shelf. + * An array of books IDs can be provided in the request. These + * will be added to the shelf in the same order as provided and overwrite + * any existing book assignments. * @throws ValidationException */ public function update(Request $request, string $id) @@ -84,9 +95,9 @@ class BookshelfApiController extends ApiController $requestData = $this->validate($request, $this->rules['update']); - $bookIds = $request->get('books', []); + $bookIds = $request->get('books', null); - $shelf = $this->bookshelfRepo->update($shelf, $requestData,$bookIds); + $shelf = $this->bookshelfRepo->update($shelf, $requestData, $bookIds); Activity::add($shelf, 'bookshelf_update', $shelf->id); return response()->json($shelf); @@ -96,8 +107,6 @@ class BookshelfApiController extends ApiController /** * Delete a single shelf from the system. - * @param string $id - * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response * @throws Exception */ public function delete(string $id) @@ -106,7 +115,7 @@ class BookshelfApiController extends ApiController $this->checkOwnablePermission('bookshelf-delete', $shelf); $this->bookshelfRepo->destroy($shelf); - Activity::addMessage('bookshelf-delete', $shelf->name); + Activity::addMessage('bookshelf_delete', $shelf->name); return response('', 204); } diff --git a/dev/api/requests/shelves-create.json b/dev/api/requests/shelves-create.json new file mode 100644 index 000000000..39b88af7e --- /dev/null +++ b/dev/api/requests/shelves-create.json @@ -0,0 +1,5 @@ +{ + "name": "My shelf", + "description": "This is my shelf with some books", + "books": [5,1,3] +} \ No newline at end of file diff --git a/dev/api/requests/shelves-update.json b/dev/api/requests/shelves-update.json new file mode 100644 index 000000000..df5f5735d --- /dev/null +++ b/dev/api/requests/shelves-update.json @@ -0,0 +1,5 @@ +{ + "name": "My updated shelf", + "description": "This is my update shelf with some books", + "books": [5,1,3] +} \ No newline at end of file diff --git a/dev/api/responses/books-read.json b/dev/api/responses/books-read.json index e0570444f..11408e9ab 100644 --- a/dev/api/responses/books-read.json +++ b/dev/api/responses/books-read.json @@ -8,15 +8,11 @@ "created_by": { "id": 1, "name": "Admin", - "created_at": "2019-05-05 21:15:13", - "updated_at": "2019-12-16 12:18:37", "image_id": 48 }, "updated_by": { "id": 1, "name": "Admin", - "created_at": "2019-05-05 21:15:13", - "updated_at": "2019-12-16 12:18:37", "image_id": 48 }, "image_id": 452, diff --git a/dev/api/responses/shelves-create.json b/dev/api/responses/shelves-create.json new file mode 100644 index 000000000..64f3c7f53 --- /dev/null +++ b/dev/api/responses/shelves-create.json @@ -0,0 +1,10 @@ +{ + "name": "My shelf", + "description": "This is my shelf with some books", + "created_by": 1, + "updated_by": 1, + "slug": "my-shelf", + "updated_at": "2020-04-10 13:24:09", + "created_at": "2020-04-10 13:24:09", + "id": 14 +} \ No newline at end of file diff --git a/dev/api/responses/shelves-list.json b/dev/api/responses/shelves-list.json new file mode 100644 index 000000000..bccd08626 --- /dev/null +++ b/dev/api/responses/shelves-list.json @@ -0,0 +1,38 @@ +{ + "data": [ + { + "id": 8, + "name": "Qui qui aspernatur autem molestiae libero necessitatibus molestias.", + "slug": "qui-qui-aspernatur-autem-molestiae-libero-necessitatibus-molestias", + "description": "Enim dolor ut quia error dolores est. Aut distinctio consequuntur non nisi nostrum. Labore cupiditate error labore aliquid provident impedit voluptatibus. Quaerat impedit excepturi eius qui eius voluptatem reiciendis.", + "created_at": "2019-05-05 22:10:16", + "updated_at": "2020-04-10 13:00:45", + "created_by": 4, + "updated_by": 1, + "image_id": 31 + }, + { + "id": 9, + "name": "Ipsum aut inventore fuga libero non facilis.", + "slug": "ipsum-aut-inventore-fuga-libero-non-facilis", + "description": "Labore culpa modi perspiciatis harum sit. Maxime non et nam est. Quae ut laboriosam repellendus sunt quisquam. Velit at est perspiciatis nesciunt adipisci nobis illo. Sed possimus odit optio officiis nisi voluptates officiis dolor.", + "created_at": "2019-05-05 22:10:16", + "updated_at": "2020-04-10 13:00:58", + "created_by": 4, + "updated_by": 1, + "image_id": 28 + }, + { + "id": 10, + "name": "Omnis reiciendis aut molestias sint accusantium.", + "slug": "omnis-reiciendis-aut-molestias-sint-accusantium", + "description": "Qui ea occaecati alias est dolores voluptatem doloribus. Ad reiciendis corporis vero nostrum omnis et. Non doloribus ut eaque ut quos dolores.", + "created_at": "2019-05-05 22:10:16", + "updated_at": "2020-04-10 13:00:53", + "created_by": 4, + "updated_by": 1, + "image_id": 30 + } + ], + "total": 3 +} \ No newline at end of file diff --git a/dev/api/responses/shelves-read.json b/dev/api/responses/shelves-read.json new file mode 100644 index 000000000..8a8e2348b --- /dev/null +++ b/dev/api/responses/shelves-read.json @@ -0,0 +1,60 @@ +{ + "id": 14, + "name": "My shelf", + "slug": "my-shelf", + "description": "This is my shelf with some books", + "created_by": { + "id": 1, + "name": "Admin", + "image_id": 48 + }, + "updated_by": { + "id": 1, + "name": "Admin", + "image_id": 48 + }, + "image_id": 501, + "created_at": "2020-04-10 13:24:09", + "updated_at": "2020-04-10 13:31:04", + "tags": [ + { + "id": 16, + "entity_id": 14, + "entity_type": "BookStack\\Bookshelf", + "name": "Category", + "value": "Guide", + "order": 0, + "created_at": "2020-04-10 13:31:04", + "updated_at": "2020-04-10 13:31:04" + } + ], + "cover": { + "id": 501, + "name": "anafrancisconi_Sp04AfFCPNM.jpg", + "url": "http://bookstack.local/uploads/images/cover_book/2020-04/anafrancisconi_Sp04AfFCPNM.jpg", + "created_at": "2020-04-10 13:31:04", + "updated_at": "2020-04-10 13:31:04", + "created_by": 1, + "updated_by": 1, + "path": "/uploads/images/cover_book/2020-04/anafrancisconi_Sp04AfFCPNM.jpg", + "type": "cover_book", + "uploaded_to": 14 + }, + "books": [ + { + "id": 5, + "name": "Sint explicabo alias sunt.", + "slug": "jbsQrzuaXe" + }, + { + "id": 1, + "name": "BookStack User Guide", + "slug": "bookstack-user-guide" + }, + { + "id": 3, + "name": "Molestiae doloribus sint velit suscipit dolorem.", + "slug": "H99QxALaoG" + } + ] +} \ No newline at end of file diff --git a/dev/api/responses/shelves-update.json b/dev/api/responses/shelves-update.json new file mode 100644 index 000000000..4820150eb --- /dev/null +++ b/dev/api/responses/shelves-update.json @@ -0,0 +1,11 @@ +{ + "id": 14, + "name": "My updated shelf", + "slug": "my-updated-shelf", + "description": "This is my update shelf with some books", + "created_by": 1, + "updated_by": 1, + "image_id": 501, + "created_at": "2020-04-10 13:24:09", + "updated_at": "2020-04-10 13:48:22" +} \ No newline at end of file diff --git a/tests/Api/ShelvesApiTest.php b/tests/Api/ShelvesApiTest.php new file mode 100644 index 000000000..13e44d97d --- /dev/null +++ b/tests/Api/ShelvesApiTest.php @@ -0,0 +1,136 @@ +actingAsApiEditor(); + $firstBookshelf = Bookshelf::query()->orderBy('id', 'asc')->first(); + + $resp = $this->getJson($this->baseEndpoint . '?count=1&sort=+id'); + $resp->assertJson(['data' => [ + [ + 'id' => $firstBookshelf->id, + 'name' => $firstBookshelf->name, + 'slug' => $firstBookshelf->slug, + ] + ]]); + } + + public function test_create_endpoint() + { + $this->actingAsApiEditor(); + $books = Book::query()->take(2)->get(); + + $details = [ + 'name' => 'My API shelf', + 'description' => 'A shelf created via the API', + ]; + + $resp = $this->postJson($this->baseEndpoint, array_merge($details, ['books' => [$books[0]->id, $books[1]->id]])); + $resp->assertStatus(200); + $newItem = Bookshelf::query()->orderByDesc('id')->where('name', '=', $details['name'])->first(); + $resp->assertJson(array_merge($details, ['id' => $newItem->id, 'slug' => $newItem->slug])); + $this->assertActivityExists('bookshelf_create', $newItem); + foreach ($books as $index => $book) { + $this->assertDatabaseHas('bookshelves_books', [ + 'bookshelf_id' => $newItem->id, + 'book_id' => $book->id, + 'order' => $index, + ]); + } + } + + public function test_shelf_name_needed_to_create() + { + $this->actingAsApiEditor(); + $details = [ + 'description' => 'A shelf created via the API', + ]; + + $resp = $this->postJson($this->baseEndpoint, $details); + $resp->assertStatus(422); + $resp->assertJson([ + "error" => [ + "message" => "The given data was invalid.", + "validation" => [ + "name" => ["The name field is required."] + ], + "code" => 422, + ], + ]); + } + + public function test_read_endpoint() + { + $this->actingAsApiEditor(); + $shelf = Bookshelf::visible()->first(); + + $resp = $this->getJson($this->baseEndpoint . "/{$shelf->id}"); + + $resp->assertStatus(200); + $resp->assertJson([ + 'id' => $shelf->id, + 'slug' => $shelf->slug, + 'created_by' => [ + 'name' => $shelf->createdBy->name, + ], + 'updated_by' => [ + 'name' => $shelf->createdBy->name, + ] + ]); + } + + public function test_update_endpoint() + { + $this->actingAsApiEditor(); + $shelf = Bookshelf::visible()->first(); + $details = [ + 'name' => 'My updated API shelf', + 'description' => 'A shelf created via the API', + ]; + + $resp = $this->putJson($this->baseEndpoint . "/{$shelf->id}", $details); + $shelf->refresh(); + + $resp->assertStatus(200); + $resp->assertJson(array_merge($details, ['id' => $shelf->id, 'slug' => $shelf->slug])); + $this->assertActivityExists('bookshelf_update', $shelf); + } + + public function test_update_only_assigns_books_if_param_provided() + { + $this->actingAsApiEditor(); + $shelf = Bookshelf::visible()->first(); + $this->assertTrue($shelf->books()->count() > 0); + $details = [ + 'name' => 'My updated API shelf', + ]; + + $resp = $this->putJson($this->baseEndpoint . "/{$shelf->id}", $details); + $resp->assertStatus(200); + $this->assertTrue($shelf->books()->count() > 0); + + $resp = $this->putJson($this->baseEndpoint . "/{$shelf->id}", ['books' => []]); + $resp->assertStatus(200); + $this->assertTrue($shelf->books()->count() === 0); + } + + public function test_delete_endpoint() + { + $this->actingAsApiEditor(); + $shelf = Bookshelf::visible()->first(); + $resp = $this->deleteJson($this->baseEndpoint . "/{$shelf->id}"); + + $resp->assertStatus(204); + $this->assertActivityExists('bookshelf_delete'); + } +} \ No newline at end of file From 7b8fe5fbc69a6f49c2acff938f1da48c28e19ecd Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 10 Apr 2020 16:05:17 +0100 Subject: [PATCH 023/197] Added book-export endpoints to the API --- app/Api/ApiDocsGenerator.php | 2 + .../Api/BooksExportApiController.php | 55 +++++++++++++++++++ resources/views/api-docs/index.blade.php | 4 +- routes/api.php | 4 ++ tests/Api/BooksApiTest.php | 32 +++++++++++ 5 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 app/Http/Controllers/Api/BooksExportApiController.php diff --git a/app/Api/ApiDocsGenerator.php b/app/Api/ApiDocsGenerator.php index a0c45608a..ddba24bdb 100644 --- a/app/Api/ApiDocsGenerator.php +++ b/app/Api/ApiDocsGenerator.php @@ -3,6 +3,7 @@ use BookStack\Http\Controllers\Api\ApiController; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Route; +use Illuminate\Support\Str; use ReflectionClass; use ReflectionException; use ReflectionMethod; @@ -117,6 +118,7 @@ class ApiDocsGenerator 'method' => $route->methods[0], 'controller' => $controller, 'controller_method' => $controllerMethod, + 'controller_method_kebab' => Str::kebab($controllerMethod), 'base_model' => $baseModelName, ]; }); diff --git a/app/Http/Controllers/Api/BooksExportApiController.php b/app/Http/Controllers/Api/BooksExportApiController.php new file mode 100644 index 000000000..605f8f408 --- /dev/null +++ b/app/Http/Controllers/Api/BooksExportApiController.php @@ -0,0 +1,55 @@ +bookRepo = $bookRepo; + $this->exportService = $exportService; + parent::__construct(); + } + + /** + * Export a book as a PDF file. + * @throws Throwable + */ + public function exportPdf(int $id) + { + $book = Book::visible()->findOrFail($id); + $pdfContent = $this->exportService->bookToPdf($book); + return $this->downloadResponse($pdfContent, $book->slug . '.pdf'); + } + + /** + * Export a book as a contained HTML file. + * @throws Throwable + */ + public function exportHtml(int $id) + { + $book = Book::visible()->findOrFail($id); + $htmlContent = $this->exportService->bookToContainedHtml($book); + return $this->downloadResponse($htmlContent, $book->slug . '.html'); + } + + /** + * Export a book as a plain text file. + */ + public function exportPlainText(int $id) + { + $book = Book::visible()->findOrFail($id); + $textContent = $this->exportService->bookToPlainText($book); + return $this->downloadResponse($textContent, $book->slug . '.txt'); + } +} diff --git a/resources/views/api-docs/index.blade.php b/resources/views/api-docs/index.blade.php index ab4db89e8..e92b505cf 100644 --- a/resources/views/api-docs/index.blade.php +++ b/resources/views/api-docs/index.blade.php @@ -26,7 +26,7 @@ {{ $endpoint['method'] }} - {{ $endpoint['controller_method'] }} + {{ $endpoint['controller_method_kebab'] }}
@endforeach @@ -186,7 +186,7 @@

{{ $model }}

@foreach($endpoints as $endpoint) -
{{ $endpoint['controller_method'] }}
+
{{ $endpoint['controller_method_kebab'] }}
{{ $endpoint['method'] }} {{ url($endpoint['uri']) }} diff --git a/routes/api.php b/routes/api.php index 7ca5e66fc..f9c27b62f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -15,6 +15,10 @@ Route::get('books/{id}', 'BooksApiController@read'); Route::put('books/{id}', 'BooksApiController@update'); Route::delete('books/{id}', 'BooksApiController@delete'); +Route::get('books/{id}/export/html', 'BooksExportApiController@exportHtml'); +Route::get('books/{id}/export/pdf', 'BooksExportApiController@exportPdf'); +Route::get('books/{id}/export/plaintext', 'BooksExportApiController@exportPlainText'); + Route::get('shelves', 'BookshelfApiController@list'); Route::post('shelves', 'BookshelfApiController@create'); Route::get('shelves/{id}', 'BookshelfApiController@read'); diff --git a/tests/Api/BooksApiTest.php b/tests/Api/BooksApiTest.php index 6f8753fb0..3fd763ec6 100644 --- a/tests/Api/BooksApiTest.php +++ b/tests/Api/BooksApiTest.php @@ -105,4 +105,36 @@ class BooksApiTest extends TestCase $resp->assertStatus(204); $this->assertActivityExists('book_delete'); } + + public function test_export_html_endpoint() + { + $this->actingAsApiEditor(); + $book = Book::visible()->first(); + + $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/html"); + $resp->assertStatus(200); + $resp->assertSee($book->name); + $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.html"'); + } + + public function test_export_plain_text_endpoint() + { + $this->actingAsApiEditor(); + $book = Book::visible()->first(); + + $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/plaintext"); + $resp->assertStatus(200); + $resp->assertSee($book->name); + $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.txt"'); + } + + public function test_export_pdf_endpoint() + { + $this->actingAsApiEditor(); + $book = Book::visible()->first(); + + $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/pdf"); + $resp->assertStatus(200); + $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.pdf"'); + } } \ No newline at end of file From d4df18098f2273472f0c648cdce236455fa31595 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 10 Apr 2020 20:55:33 +0100 Subject: [PATCH 024/197] Cleaned up the activity service - Added test to ensure activity on entity delete works as expected. --- app/Actions/Activity.php | 4 +- app/Actions/ActivityService.php | 88 ++++++++++++--------------------- tests/Entity/EntityTest.php | 31 ++++++++++++ 3 files changed, 64 insertions(+), 59 deletions(-) diff --git a/app/Actions/Activity.php b/app/Actions/Activity.php index 05f0129dd..035a9cc75 100644 --- a/app/Actions/Activity.php +++ b/app/Actions/Activity.php @@ -50,10 +50,8 @@ class Activity extends Model /** * Checks if another Activity matches the general information of another. - * @param $activityB - * @return bool */ - public function isSimilarTo($activityB) + public function isSimilarTo(Activity $activityB): bool { return [$this->key, $this->entity_type, $this->entity_id] === [$activityB->key, $activityB->entity_type, $activityB->entity_id]; } diff --git a/app/Actions/ActivityService.php b/app/Actions/ActivityService.php index f56f1ca57..a92447cff 100644 --- a/app/Actions/ActivityService.php +++ b/app/Actions/ActivityService.php @@ -1,8 +1,9 @@ newActivityForUser($activityKey, $bookId); $entity->activity()->save($activity); @@ -37,11 +33,8 @@ class ActivityService /** * Adds a activity history with a message, without binding to a entity. - * @param string $activityKey - * @param string $message - * @param int $bookId */ - public function addMessage(string $activityKey, string $message, int $bookId = null) + public function addMessage(string $activityKey, string $message, ?int $bookId = null) { $this->newActivityForUser($activityKey, $bookId)->forceFill([ 'extra' => $message @@ -52,11 +45,8 @@ class ActivityService /** * Get a new activity instance for the current user. - * @param string $key - * @param int|null $bookId - * @return Activity */ - protected function newActivityForUser(string $key, int $bookId = null) + protected function newActivityForUser(string $key, ?int $bookId = null): Activity { return $this->activity->newInstance()->forceFill([ 'key' => strtolower($key), @@ -69,34 +59,27 @@ class ActivityService * Removes the entity attachment from each of its activities * and instead uses the 'extra' field with the entities name. * Used when an entity is deleted. - * @param \BookStack\Entities\Entity $entity - * @return mixed */ - public function removeEntity(Entity $entity) + public function removeEntity(Entity $entity): Collection { - // TODO - Rewrite to db query. - $activities = $entity->activity; - foreach ($activities as $activity) { - $activity->extra = $entity->name; - $activity->entity_id = 0; - $activity->entity_type = null; - $activity->save(); - } + $activities = $entity->activity()->get(); + $entity->activity()->update([ + 'extra' => $entity->name, + 'entity_id' => 0, + 'entity_type' => '', + ]); return $activities; } /** * Gets the latest activity. - * @param int $count - * @param int $page - * @return array */ - public function latest($count = 20, $page = 0) + public function latest(int $count = 20, int $page = 0): array { $activityList = $this->permissionService ->filterRestrictedEntityRelations($this->activity, 'activities', 'entity_id', 'entity_type') ->orderBy('created_at', 'desc') - ->with('user', 'entity') + ->with(['user', 'entity']) ->skip($count * $page) ->take($count) ->get(); @@ -107,17 +90,13 @@ class ActivityService /** * Gets the latest activity for an entity, Filtering out similar * items to prevent a message activity list. - * @param \BookStack\Entities\Entity $entity - * @param int $count - * @param int $page - * @return array */ - public function entityActivity($entity, $count = 20, $page = 1) + public function entityActivity(Entity $entity, int $count = 20, int $page = 1): array { if ($entity->isA('book')) { - $query = $this->activity->where('book_id', '=', $entity->id); + $query = $this->activity->newQuery()->where('book_id', '=', $entity->id); } else { - $query = $this->activity->where('entity_type', '=', $entity->getMorphClass()) + $query = $this->activity->newQuery()->where('entity_type', '=', $entity->getMorphClass()) ->where('entity_id', '=', $entity->id); } @@ -133,18 +112,18 @@ class ActivityService } /** - * Get latest activity for a user, Filtering out similar - * items. - * @param $user - * @param int $count - * @param int $page - * @return array + * Get latest activity for a user, Filtering out similar items. */ - public function userActivity($user, $count = 20, $page = 0) + public function userActivity(User $user, int $count = 20, int $page = 0): array { $activityList = $this->permissionService ->filterRestrictedEntityRelations($this->activity, 'activities', 'entity_id', 'entity_type') - ->orderBy('created_at', 'desc')->where('user_id', '=', $user->id)->skip($count * $page)->take($count)->get(); + ->orderBy('created_at', 'desc') + ->where('user_id', '=', $user->id) + ->skip($count * $page) + ->take($count) + ->get()->toArray(); + return $this->filterSimilar($activityList); } @@ -153,29 +132,26 @@ class ActivityService * @param Activity[] $activities * @return array */ - protected function filterSimilar($activities) + protected function filterSimilar(iterable $activities): array { $newActivity = []; - $previousItem = false; + $previousItem = null; + foreach ($activities as $activityItem) { - if ($previousItem === false) { - $previousItem = $activityItem; - $newActivity[] = $activityItem; - continue; - } - if (!$activityItem->isSimilarTo($previousItem)) { + if (!$previousItem || !$activityItem->isSimilarTo($previousItem)) { $newActivity[] = $activityItem; } + $previousItem = $activityItem; } + return $newActivity; } /** * Flashes a notification message to the session if an appropriate message is available. - * @param $activityKey */ - protected function setNotification($activityKey) + protected function setNotification(string $activityKey) { $notificationTextKey = 'activities.' . $activityKey . '_notification'; if (trans()->has($notificationTextKey)) { diff --git a/tests/Entity/EntityTest.php b/tests/Entity/EntityTest.php index 6d71d6090..d7e4ec61c 100644 --- a/tests/Entity/EntityTest.php +++ b/tests/Entity/EntityTest.php @@ -7,6 +7,7 @@ use BookStack\Entities\Page; use BookStack\Auth\UserRepo; use BookStack\Entities\Repos\PageRepo; use Carbon\Carbon; +use Illuminate\Support\Facades\DB; use Tests\BrowserKitTest; class EntityTest extends BrowserKitTest @@ -326,4 +327,34 @@ class EntityTest extends BrowserKitTest ->seePageIs($chapter->getUrl()); } + public function test_page_delete_removes_entity_from_its_activity() + { + $page = Page::query()->first(); + + $this->asEditor()->put($page->getUrl(), [ + 'name' => 'My updated page', + 'html' => '

updated content

', + ]); + $page->refresh(); + + $this->seeInDatabase('activities', [ + 'entity_id' => $page->id, + 'entity_type' => $page->getMorphClass(), + ]); + + $resp = $this->delete($page->getUrl()); + $resp->assertResponseStatus(302); + + $this->dontSeeInDatabase('activities', [ + 'entity_id' => $page->id, + 'entity_type' => $page->getMorphClass(), + ]); + + $this->seeInDatabase('activities', [ + 'extra' => 'My updated page', + 'entity_id' => 0, + 'entity_type' => '', + ]); + } + } From 1ba5a1274c7edeebaa530ee3d48d979f6833515f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 10 Apr 2020 22:38:29 +0100 Subject: [PATCH 025/197] Started work on supporting a dark-mode - Most elements done, but still need to do editors, tables and final pass. - Toggled only by quick js check at the moment, checking via css media query. Need to make into user-preference toggle. For #1234 --- resources/js/services/code.js | 3 +- resources/sass/_blocks.scss | 2 +- resources/sass/_buttons.scss | 7 ++- resources/sass/_codemirror.scss | 71 ++++++++++++++++++++++-- resources/sass/_colors.scss | 8 +-- resources/sass/_forms.scss | 9 +-- resources/sass/_header.scss | 9 +-- resources/sass/_html.scss | 6 +- resources/sass/_lists.scss | 23 ++++---- resources/sass/_mixins.scss | 14 +++++ resources/sass/_tables.scss | 2 +- resources/sass/_text.scss | 28 ++++++---- resources/sass/_variables.scss | 1 + resources/sass/styles.scss | 5 +- resources/views/base.blade.php | 5 ++ resources/views/settings/index.blade.php | 12 ++-- 16 files changed, 149 insertions(+), 56 deletions(-) diff --git a/resources/js/services/code.js b/resources/js/services/code.js index 14801de9c..a7dfa587f 100644 --- a/resources/js/services/code.js +++ b/resources/js/services/code.js @@ -191,7 +191,8 @@ function getMode(suggestion, content) { * @returns {*|string} */ function getTheme() { - return window.codeTheme || 'default'; + const darkMode = document.documentElement.classList.contains('dark-mode'); + return window.codeTheme || (darkMode ? 'darcula' : 'default'); } /** diff --git a/resources/sass/_blocks.scss b/resources/sass/_blocks.scss index d02d25db4..9e04420a0 100644 --- a/resources/sass/_blocks.scss +++ b/resources/sass/_blocks.scss @@ -58,7 +58,7 @@ */ .card { - background-color: #FFF; + @include lightDark(background-color, #FFF, #222); box-shadow: $bs-card; border-radius: 3px; border: 1px solid transparent; diff --git a/resources/sass/_buttons.scss b/resources/sass/_buttons.scss index 7df1d61a4..8c8bac54e 100644 --- a/resources/sass/_buttons.scss +++ b/resources/sass/_buttons.scss @@ -22,17 +22,17 @@ button { box-shadow: none; background-color: var(--color-primary); color: #FFF; - fill: #FFF; text-transform: uppercase; border: 1px solid var(--color-primary); vertical-align: top; + @include lightDark(filter, none, saturate(0.8) brightness(0.8)); &:hover, &:focus, &:active { background-color: var(--color-primary); text-decoration: none; color: #FFFFFF; } &:hover { - box-shadow: $bs-light; + @include lightDark(box-shadow, $bs-light, $bs-dark); filter: brightness(110%); } &:focus { @@ -48,13 +48,14 @@ button { .button.outline { background-color: transparent; - color: #666; + @include lightDark(color, #666, #aaa); fill: currentColor; border: 1px solid #CCC; &:hover, &:focus, &:active { border: 1px solid #CCC; box-shadow: none; background-color: #F2F2F2; + @include lightDark(background-color, #f2f2f2, #555); filter: none; } &:active { diff --git a/resources/sass/_codemirror.scss b/resources/sass/_codemirror.scss index dc1aef9bb..c679e4899 100644 --- a/resources/sass/_codemirror.scss +++ b/resources/sass/_codemirror.scss @@ -390,6 +390,63 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} /* STOP */ +/** + * Codemirror Darcula theme + */ + +/** + Name: IntelliJ IDEA darcula theme + From IntelliJ IDEA by JetBrains + */ + +.cm-s-darcula { font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif;} +.cm-s-darcula.CodeMirror { background: #2B2B2B; color: #A9B7C6; } + +.cm-s-darcula span.cm-meta { color: #BBB529; } +.cm-s-darcula span.cm-number { color: #6897BB; } +.cm-s-darcula span.cm-keyword { color: #CC7832; line-height: 1em; font-weight: bold; } +.cm-s-darcula span.cm-def { color: #A9B7C6; font-style: italic; } +.cm-s-darcula span.cm-variable { color: #A9B7C6; } +.cm-s-darcula span.cm-variable-2 { color: #A9B7C6; } +.cm-s-darcula span.cm-variable-3 { color: #9876AA; } +.cm-s-darcula span.cm-type { color: #AABBCC; font-weight: bold; } +.cm-s-darcula span.cm-property { color: #FFC66D; } +.cm-s-darcula span.cm-operator { color: #A9B7C6; } +.cm-s-darcula span.cm-string { color: #6A8759; } +.cm-s-darcula span.cm-string-2 { color: #6A8759; } +.cm-s-darcula span.cm-comment { color: #61A151; font-style: italic; } +.cm-s-darcula span.cm-link { color: #CC7832; } +.cm-s-darcula span.cm-atom { color: #CC7832; } +.cm-s-darcula span.cm-error { color: #BC3F3C; } +.cm-s-darcula span.cm-tag { color: #629755; font-weight: bold; font-style: italic; text-decoration: underline; } +.cm-s-darcula span.cm-attribute { color: #6897bb; } +.cm-s-darcula span.cm-qualifier { color: #6A8759; } +.cm-s-darcula span.cm-bracket { color: #A9B7C6; } +.cm-s-darcula span.cm-builtin { color: #FF9E59; } +.cm-s-darcula span.cm-special { color: #FF9E59; } +.cm-s-darcula span.cm-matchhighlight { color: #FFFFFF; background-color: rgba(50, 89, 48, .7); font-weight: normal;} +.cm-s-darcula span.cm-searching { color: #FFFFFF; background-color: rgba(61, 115, 59, .7); font-weight: normal;} + +.cm-s-darcula .CodeMirror-cursor { border-left: 1px solid #A9B7C6; } +.cm-s-darcula .CodeMirror-activeline-background { background: #323232; } +.cm-s-darcula .CodeMirror-gutters { background: #313335; border-right: 1px solid #313335; } +.cm-s-darcula .CodeMirror-guttermarker { color: #FFEE80; } +.cm-s-darcula .CodeMirror-guttermarker-subtle { color: #D0D0D0; } +.cm-s-darcula .CodeMirrir-linenumber { color: #606366; } +.cm-s-darcula .CodeMirror-matchingbracket { background-color: #3B514D; color: #FFEF28 !important; font-weight: bold; } + +.cm-s-darcula div.CodeMirror-selected { background: #214283; } + +.CodeMirror-hints.darcula { + font-family: Menlo, Monaco, Consolas, 'Courier New', monospace; + color: #9C9E9E; + background-color: #3B3E3F !important; +} + +.CodeMirror-hints.darcula .CodeMirror-hint-active { + background-color: #494D4E !important; + color: #9C9E9E !important; +} /** * Custom BookStack overrides @@ -401,7 +458,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} font-size: 12px; height: auto; margin-bottom: $-l; - border: 1px solid #DDD;; + border: 1px solid; + @include lightDark(border-color, #DDD, #111) } .cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 0; color: #333; } @@ -424,24 +482,25 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} top: -1px; right: -1px; background-color: #EEE; + border: 1px solid #DDD; + @include lightDark(background-color, #eee, #333); + @include lightDark(border-color, #ddd, #444); + @include lightDark(fill, #444, #888); padding: $-xs; line-height: 0; - border: 1px solid #DDD; cursor: pointer; - fill: #444; z-index: 5; - transition: all ease-in 240ms; user-select: none; opacity: 0; pointer-events: none; svg { - transition: transform ease-in 240ms; + transition: all ease-in 240ms; transform: translateY(0); } &.success { background-color: lighten($positive, 10%); - fill: #FFF; svg { + fill: #FFF; transform: translateY(-3px); } } diff --git a/resources/sass/_colors.scss b/resources/sass/_colors.scss index 77f51b324..e9ddd2214 100644 --- a/resources/sass/_colors.scss +++ b/resources/sass/_colors.scss @@ -36,13 +36,13 @@ } .text-muted { - color: #575757 !important; - fill: #575757 !important; + @include lightDark(color, #575757, #888888, true); + fill: currentColor !important; } .text-dark { - color: #222 !important; - fill: #222 !important; + @include lightDark(color, #222, #ccc, true); + fill: currentColor !important; } /* diff --git a/resources/sass/_forms.scss b/resources/sass/_forms.scss index f306a717b..535bc54ea 100644 --- a/resources/sass/_forms.scss +++ b/resources/sass/_forms.scss @@ -1,12 +1,13 @@ .input-base { - background-color: #FFF; border-radius: 3px; border: 1px solid #D4D4D4; + @include lightDark(background-color, #fff, #333); + @include lightDark(border-color, #d4d4d4, #111); + @include lightDark(color, #666, #AAA); display: inline-block; - font-size: $fs-s; + font-size: $fs-m; padding: $-xs*1.5; - color: #666; width: 250px; max-width: 100%; @@ -139,11 +140,11 @@ label { + @include lightDark(color, #666, #ddd); display: block; line-height: 1.4em; font-size: 0.94em; font-weight: 400; - color: #666; padding-bottom: 2px; margin-bottom: 0.2em; &.inline { diff --git a/resources/sass/_header.scss b/resources/sass/_header.scss index 5503a0895..1c4bf948f 100644 --- a/resources/sass/_header.scss +++ b/resources/sass/_header.scss @@ -18,11 +18,14 @@ header { display: block; z-index: 11; top: 0; - color: #fff; - fill: #fff; + color: rgb(250, 250, 250); border-bottom: 1px solid #DDD; box-shadow: $bs-card; padding: $-xxs 0; + @include lightDark(border-bottom-color, #DDD, #000); + @include whenDark { + filter: saturate(0.6) brightness(0.8); + } .links { display: inline-block; vertical-align: top; @@ -31,7 +34,6 @@ header { display: inline-block; padding: $-m; color: #FFF; - fill: #FFF; } .dropdown-container { padding-inline-start: $-m; @@ -94,7 +96,6 @@ header .search-box { } } button { - fill: #EEE; z-index: 1; left: 16px; @include rtl { diff --git a/resources/sass/_html.scss b/resources/sass/_html.scss index e4a8c14bb..57869d652 100644 --- a/resources/sass/_html.scss +++ b/resources/sass/_html.scss @@ -15,12 +15,14 @@ html { &.flexbox { overflow-y: hidden; } + &.dark-mode { + background-color: #111; + } } body { font-size: $fs-m; line-height: 1.6; - color: #444; + @include lightDark(color, #444, #AAA); -webkit-font-smoothing: antialiased; - background-color: #F2F2F2; } \ No newline at end of file diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 7beb63d4e..2e12c2009 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -99,7 +99,7 @@ left: auto; right: 0; } - background-color: rgba(0, 0, 0, 0.2); + @include lightDark(background-color, rgba(0, 0, 0, 0.2), rgba(255, 255, 255, 0.2)); width: 2px; top: 5px; bottom: 5px; @@ -132,7 +132,7 @@ font-weight: bold; } li:not(.current-heading) .sidebar-page-nav-bullet { - background-color: #BBB !important; + @include lightDark(background-color, #BBB, #666, true); } .sidebar-page-nav-bullet { width: 6px; @@ -142,6 +142,7 @@ top: 30%; border-radius: 50%; box-shadow: 0 0 0 6px #F2F2F2; + @include lightDark(box-shadow, 0 0 0 6px #F2F2F2, 0 0 0 6px #111); z-index: 1; @include rtl { left: auto; @@ -438,7 +439,7 @@ ul.pagination { border-color: rgba(0, 0, 0, 0.1); } &:focus { - background-color: #eee; + @include lightDark(background-color, #eee, #222); outline: 1px dotted #666; outline-offset: -2px; } @@ -455,7 +456,7 @@ ul.pagination { } .card .entity-list-item:not(.no-hover):hover { - background-color: #F2F2F2; + @include lightDark(background-color, #F2F2F2, #2d2d2d) } .card .entity-list-item .entity-list-item:hover { background-color: #EEEEEE; @@ -554,14 +555,15 @@ ul.pagination { list-style: none; right: 0; margin: $-m 0; - background-color: #FFFFFF; + @include lightDark(background-color, #fff, #333); box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.1); border-radius: 1px; border: 1px solid #EEE; + @include lightDark(border-color, #eee, #000); min-width: 180px; padding: $-xs 0; - color: #555; - fill: #555; + @include lightDark(color, #555, #eee); + fill: currentColor; text-align: start !important; &.wide { min-width: 220px; @@ -576,7 +578,7 @@ ul.pagination { a, button { display: block; padding: $-xs $-m; - color: #555; + @include lightDark(color, #555, #eee); fill: currentColor; white-space: nowrap; &:hover, &:focus { @@ -653,11 +655,10 @@ ul.pagination { padding: $-s; } a:not(.active) { - color: #444; - fill: #444; + @include lightDark(color, #444, #666); } a:hover { - background-color: rgba(0, 0, 0, 0.05); + @include lightDark(background-color, rgba(0, 0, 0, 0.05), rgba(255, 255, 255, 0.05)); border-radius: 3px; text-decoration: none; } diff --git a/resources/sass/_mixins.scss b/resources/sass/_mixins.scss index 8a6becf6b..0a419c08a 100644 --- a/resources/sass/_mixins.scss +++ b/resources/sass/_mixins.scss @@ -31,4 +31,18 @@ html[dir=rtl] & { @content; } +} + +// Define a property for both light and dark mode +@mixin lightDark($prop, $light, $dark, $important: false) { + #{$prop}: if($important, $light !important, $light); + html.dark-mode & { + #{$prop}: if($important, $dark !important, $dark); + } +} + +@mixin whenDark { + html.dark-mode & { + @content; + } } \ No newline at end of file diff --git a/resources/sass/_tables.scss b/resources/sass/_tables.scss index 277873608..d0a920efc 100644 --- a/resources/sass/_tables.scss +++ b/resources/sass/_tables.scss @@ -33,7 +33,7 @@ table.table { font-weight: bold; } tr:hover { - background-color: #EEE; + @include lightDark(background-color, #eee, #333); } .text-right { text-align: end; diff --git a/resources/sass/_text.scss b/resources/sass/_text.scss index 8d2759b91..e62972497 100644 --- a/resources/sass/_text.scss +++ b/resources/sass/_text.scss @@ -42,7 +42,7 @@ h1, h2, h3, h4, h5, h6 { font-weight: 400; position: relative; display: block; - color: #222; + @include lightDark(color, #222, #BBB); .subheader { font-size: 0.5em; line-height: 1em; @@ -91,11 +91,14 @@ h2.list-heading { */ a { color: var(--color-primary); - fill: var(--color-primary); + fill: currentColor; cursor: pointer; text-decoration: none; transition: filter ease-in-out 80ms; line-height: 1.6; + @include whenDark { + filter: brightness(1.3) saturate(0.7); + } &:hover { text-decoration: underline; } @@ -130,7 +133,7 @@ p, ul, ol, pre, table, blockquote { hr { border: 0; height: 1px; - background: #EAEAEA; + @include lightDark(background, #eaeaea, #222); margin-bottom: $-l; &.faded { background-image: linear-gradient(to right, #FFF, #e3e0e0 20%, #e3e0e0 80%, #FFF); @@ -153,7 +156,7 @@ em, i, .italic { small, p.small, span.small, .text-small { font-size: 0.75rem; - color: lighten($text-dark, 10%); + @include lightDark(color, #5e5e5e, #999); } sup, .superscript { @@ -168,8 +171,9 @@ sub, .subscript { pre { font-size: 12px; - background-color: #f5f5f5; border: 1px solid #DDD; + @include lightDark(background-color, #f5f5f5, #2B2B2B); + @include lightDark(border-color, #DDD, #111); padding-left: 31px; position: relative; padding-top: 3px; @@ -181,9 +185,9 @@ pre { top: 0; width: 29px; left: 0; - background-color: #f5f5f5; height: 100%; - border-right: 1px solid #DDD; + @include lightDark(background-color, #f5f5f5, #313335); + @include lightDark(border-right, 1px solid #DDD, none); } } @@ -226,10 +230,11 @@ blockquote { } .code-base { - background-color: #F8F8F8; - font-size: 0.80em; - border: 1px solid #DDD; - border-radius: 3px; + font-size: 0.84em; + border: 1px solid #DDD; + border-radius: 3px; + @include lightDark(background-color, #f8f8f8f, #2b2b2b); + @include lightDark(border-color, #DDD, #444); } code { @@ -385,4 +390,5 @@ span.sep { bottom: -0.105em; margin-inline-end: $-xs; pointer-events: none; + fill: currentColor; } diff --git a/resources/sass/_variables.scss b/resources/sass/_variables.scss index 2d4d3970a..061a83746 100644 --- a/resources/sass/_variables.scss +++ b/resources/sass/_variables.scss @@ -63,6 +63,7 @@ $text-light: #EEE; // Shadows $bs-light: 0 0 4px 1px #CCC; +$bs-dark: 0 0 4px 1px rgba(0, 0, 0, 0.5); $bs-med: 0 1px 3px 1px rgba(76, 76, 76, 0.26); $bs-large: 0 1px 6px 1px rgba(22, 22, 22, 0.2); $bs-card: 0 1px 6px -1px rgba(0, 0, 0, 0.1); diff --git a/resources/sass/styles.scss b/resources/sass/styles.scss index 09d8b4100..74e4a4fde 100644 --- a/resources/sass/styles.scss +++ b/resources/sass/styles.scss @@ -161,6 +161,7 @@ $btt-size: 40px; .entity-selector { border: 1px solid #DDD; + @include lightDark(border-color, #ddd, #111); border-radius: 3px; overflow: hidden; font-size: 0.8em; @@ -176,12 +177,12 @@ $btt-size: 40px; .entity-list { overflow-y: scroll; height: 400px; - background-color: #EEEEEE; + @include lightDark(background-color, #eee, #222); margin-inline-end: 0; margin-inline-start: 0; } .entity-list-item { - background-color: #FFF; + @include lightDark(background-color, #fff, #222); } .entity-list-item p { margin-bottom: 0; diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index d362ef373..0f43532fb 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -24,6 +24,11 @@ @stack('translations') + diff --git a/resources/views/settings/index.blade.php b/resources/views/settings/index.blade.php index 07ca1fcc1..6ccb8d8f9 100644 --- a/resources/views/settings/index.blade.php +++ b/resources/views/settings/index.blade.php @@ -92,7 +92,7 @@

{{ trans('settings.app_name_desc') }}

-
+
@include('components.toggle-switch', [ 'name' => 'setting-app-name-header', @@ -107,7 +107,7 @@

{{ trans('settings.app_editor_desc') }}

-
+
@@ -174,7 +174,7 @@

{{ trans('settings.app_homepage_desc') }}

-
+
From 627720c5afb744dae06f0d31b15937bbebea76f6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 10 Apr 2020 22:49:52 +0100 Subject: [PATCH 026/197] Fixed incorrect []Activity -> array conversion --- app/Actions/ActivityService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Actions/ActivityService.php b/app/Actions/ActivityService.php index a92447cff..9b69cbb17 100644 --- a/app/Actions/ActivityService.php +++ b/app/Actions/ActivityService.php @@ -122,7 +122,7 @@ class ActivityService ->where('user_id', '=', $user->id) ->skip($count * $page) ->take($count) - ->get()->toArray(); + ->get(); return $this->filterSimilar($activityList); } From df8ea0b81d595a65b1078b944292113b044c37e8 Mon Sep 17 00:00:00 2001 From: jzoy Date: Sat, 11 Apr 2020 21:26:13 +0800 Subject: [PATCH 027/197] fix Chinese translation error --- resources/lang/zh_CN/settings.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/zh_CN/settings.php b/resources/lang/zh_CN/settings.php index bc01ff7ab..6c3633c8a 100755 --- a/resources/lang/zh_CN/settings.php +++ b/resources/lang/zh_CN/settings.php @@ -57,9 +57,9 @@ return [ 'reg_enable_desc' => '启用注册后,用户将可以自己注册为站点用户。 注册后,他们将获得一个默认的单一用户角色。', 'reg_default_role' => '注册后的默认用户角色', 'reg_enable_external_warning' => '当启用外部LDAP或者SAML认证时,上面的选项会被忽略。当使用外部系统认证认证成功时,将自动创建非现有会员的用户账户。', - 'reg_email_confirmation' => '邮箱确认n', + 'reg_email_confirmation' => '电子邮件确认', 'reg_email_confirmation_toggle' => '需要电子邮件确认', - 'reg_confirm_email_desc' => '如果使用域名限制,则需要Email验证,并且该值将被忽略。', + 'reg_confirm_email_desc' => '如果启用域名限制功能,则自动开启电子邮箱确认,并且本设定将被忽略。', 'reg_confirm_restrict_domain' => '域名限制', 'reg_confirm_restrict_domain_desc' => '输入您想要限制注册的Email域名列表,用逗号隔开。在被允许与应用程序交互之前,用户将被发送一封Email来确认他们的地址。
注意用户在注册成功后可以修改他们的Email地址。', 'reg_confirm_restrict_domain_placeholder' => '尚未设置限制', From eb94500dcadb7c226a2e73eb3dbddb8077db5928 Mon Sep 17 00:00:00 2001 From: jzoy Date: Sat, 11 Apr 2020 21:29:09 +0800 Subject: [PATCH 028/197] Update settings.php --- resources/lang/zh_CN/settings.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/zh_CN/settings.php b/resources/lang/zh_CN/settings.php index 6c3633c8a..b7dded317 100755 --- a/resources/lang/zh_CN/settings.php +++ b/resources/lang/zh_CN/settings.php @@ -58,8 +58,8 @@ return [ 'reg_default_role' => '注册后的默认用户角色', 'reg_enable_external_warning' => '当启用外部LDAP或者SAML认证时,上面的选项会被忽略。当使用外部系统认证认证成功时,将自动创建非现有会员的用户账户。', 'reg_email_confirmation' => '电子邮件确认', - 'reg_email_confirmation_toggle' => '需要电子邮件确认', - 'reg_confirm_email_desc' => '如果启用域名限制功能,则自动开启电子邮箱确认,并且本设定将被忽略。', + 'reg_email_confirmation_toggle' => '新用户注册时,需要电子邮件确认', + 'reg_confirm_email_desc' => '如果启用域名限制功能,则自动开启电子邮件确认,并且本项设定将被忽略。', 'reg_confirm_restrict_domain' => '域名限制', 'reg_confirm_restrict_domain_desc' => '输入您想要限制注册的Email域名列表,用逗号隔开。在被允许与应用程序交互之前,用户将被发送一封Email来确认他们的地址。
注意用户在注册成功后可以修改他们的Email地址。', 'reg_confirm_restrict_domain_placeholder' => '尚未设置限制', From b0b28e7b5e5859cd676ad2e5704f244ca94422e9 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 11 Apr 2020 15:48:08 +0100 Subject: [PATCH 029/197] Rolled dark mode out to the editors - Updated editor, and other area, styles to look okay in dark mode. - Used tinyMCE theme generator to create dark mode theme. - Updated tinymce to latest 4x version. --- .../libs/tinymce/plugins/help/plugin.min.js | 2 +- .../libs/tinymce/plugins/image/plugin.min.js | 2 +- .../tinymce/plugins/imagetools/plugin.min.js | 2 +- .../libs/tinymce/plugins/lists/plugin.min.js | 2 +- .../libs/tinymce/plugins/paste/plugin.min.js | 2 +- .../libs/tinymce/plugins/print/plugin.min.js | 2 +- .../libs/tinymce/plugins/table/plugin.min.js | 2 +- .../tinymce/plugins/textpattern/plugin.min.js | 2 +- .../tinymce/plugins/visualchars/plugin.min.js | 2 +- .../tinymce/plugins/wordcount/plugin.min.js | 2 +- public/libs/tinymce/skins/dark/Variables.less | 224 ++ .../tinymce/skins/dark/content.inline.min.css | 1 + .../libs/tinymce/skins/dark/content.min.css | 1 + .../libs/tinymce/skins/dark/fonts/readme.md | 1 + .../skins/dark/fonts/tinymce-small.eot | Bin 0 -> 9492 bytes .../skins/dark/fonts/tinymce-small.json | 1277 +++++++ .../skins/dark/fonts/tinymce-small.svg | 63 + .../skins/dark/fonts/tinymce-small.ttf | Bin 0 -> 9304 bytes .../skins/dark/fonts/tinymce-small.woff | Bin 0 -> 9380 bytes .../libs/tinymce/skins/dark/fonts/tinymce.eot | Bin 0 -> 17572 bytes .../tinymce/skins/dark/fonts/tinymce.json | 3381 +++++++++++++++++ .../libs/tinymce/skins/dark/fonts/tinymce.svg | 131 + .../libs/tinymce/skins/dark/fonts/tinymce.ttf | Bin 0 -> 17408 bytes .../tinymce/skins/dark/fonts/tinymce.woff | Bin 0 -> 17484 bytes public/libs/tinymce/skins/dark/img/anchor.gif | Bin 0 -> 53 bytes public/libs/tinymce/skins/dark/img/loader.gif | Bin 0 -> 2608 bytes public/libs/tinymce/skins/dark/img/object.gif | Bin 0 -> 152 bytes public/libs/tinymce/skins/dark/img/trans.gif | Bin 0 -> 43 bytes .../libs/tinymce/skins/dark/skin.ie7.min.css | 1 + public/libs/tinymce/skins/dark/skin.json | 79 + public/libs/tinymce/skins/dark/skin.min.css | 1 + .../skins/lightgray/content.inline.min.css | 2 +- .../tinymce/skins/lightgray/content.min.css | 2 +- public/libs/tinymce/tinymce.min.js | 4 +- resources/js/components/markdown-editor.js | 8 +- resources/js/components/wysiwyg-editor.js | 20 +- resources/js/vues/components/autosuggest.js | 2 +- resources/sass/_blocks.scss | 29 +- resources/sass/_buttons.scss | 4 +- resources/sass/_colors.scss | 14 +- resources/sass/_components.scss | 29 +- resources/sass/_forms.scss | 23 +- resources/sass/_lists.scss | 6 +- resources/sass/_pages.scss | 11 +- resources/sass/_tables.scss | 2 +- resources/sass/_text.scss | 2 +- resources/sass/_tinymce.scss | 4 +- resources/sass/_variables.scss | 1 + resources/sass/styles.scss | 10 +- .../views/components/image-manager.blade.php | 2 +- 50 files changed, 5286 insertions(+), 69 deletions(-) create mode 100644 public/libs/tinymce/skins/dark/Variables.less create mode 100644 public/libs/tinymce/skins/dark/content.inline.min.css create mode 100644 public/libs/tinymce/skins/dark/content.min.css create mode 100644 public/libs/tinymce/skins/dark/fonts/readme.md create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce-small.eot create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce-small.json create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce-small.svg create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce-small.ttf create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce-small.woff create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce.eot create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce.json create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce.svg create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce.ttf create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce.woff create mode 100644 public/libs/tinymce/skins/dark/img/anchor.gif create mode 100644 public/libs/tinymce/skins/dark/img/loader.gif create mode 100644 public/libs/tinymce/skins/dark/img/object.gif create mode 100644 public/libs/tinymce/skins/dark/img/trans.gif create mode 100644 public/libs/tinymce/skins/dark/skin.ie7.min.css create mode 100644 public/libs/tinymce/skins/dark/skin.json create mode 100644 public/libs/tinymce/skins/dark/skin.min.css diff --git a/public/libs/tinymce/plugins/help/plugin.min.js b/public/libs/tinymce/plugins/help/plugin.min.js index a598b6c4a..67cde482a 100644 --- a/public/libs/tinymce/plugins/help/plugin.min.js +++ b/public/libs/tinymce/plugins/help/plugin.min.js @@ -1 +1 @@ -!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(e){return function(){return e}};function c(r){for(var o=[],e=1;e'+C.translate(e.action)+""+e.shortcut+"";var t}).join("");return{title:"Handy Shortcuts",type:"container",style:"overflow-y: auto; overflow-x: hidden; max-height: 250px",items:[{type:"container",html:'
"+e+"
'+C.translate("Action")+""+C.translate("Shortcut")+"
"}]}},P=Object.keys,_=[{key:"advlist",name:"Advanced List"},{key:"anchor",name:"Anchor"},{key:"autolink",name:"Autolink"},{key:"autoresize",name:"Autoresize"},{key:"autosave",name:"Autosave"},{key:"bbcode",name:"BBCode"},{key:"charmap",name:"Character Map"},{key:"code",name:"Code"},{key:"codesample",name:"Code Sample"},{key:"colorpicker",name:"Color Picker"},{key:"compat3x",name:"3.x Compatibility"},{key:"contextmenu",name:"Context Menu"},{key:"directionality",name:"Directionality"},{key:"emoticons",name:"Emoticons"},{key:"fullpage",name:"Full Page"},{key:"fullscreen",name:"Full Screen"},{key:"help",name:"Help"},{key:"hr",name:"Horizontal Rule"},{key:"image",name:"Image"},{key:"imagetools",name:"Image Tools"},{key:"importcss",name:"Import CSS"},{key:"insertdatetime",name:"Insert Date/Time"},{key:"legacyoutput",name:"Legacy Output"},{key:"link",name:"Link"},{key:"lists",name:"Lists"},{key:"media",name:"Media"},{key:"nonbreaking",name:"Nonbreaking"},{key:"noneditable",name:"Noneditable"},{key:"pagebreak",name:"Page Break"},{key:"paste",name:"Paste"},{key:"preview",name:"Preview"},{key:"print",name:"Print"},{key:"save",name:"Save"},{key:"searchreplace",name:"Search and Replace"},{key:"spellchecker",name:"Spell Checker"},{key:"tabfocus",name:"Tab Focus"},{key:"table",name:"Table"},{key:"template",name:"Template"},{key:"textcolor",name:"Text Color"},{key:"textpattern",name:"Text Pattern"},{key:"toc",name:"Table of Contents"},{key:"visualblocks",name:"Visual Blocks"},{key:"visualchars",name:"Visual Characters"},{key:"wordcount",name:"Word Count"}],H=c(function(e,o){return e.replace(/\$\{([^{}]*)\}/g,function(e,t){var n,r=o[t];return"string"==(n=typeof r)||"number"===n?r.toString():e})},'${name}'),F=function(t,n){return function(e,t){for(var n=0,r=e.length;n"+F(t,e)+""}),i=a.length,l=a.join("");return"

"+C.translate(["Plugins installed ({0}):",i])+"

    "+l+"
"},E=function(e){return{title:"Plugins",type:"container",style:"overflow-y: auto; overflow-x: hidden;",layout:"flex",padding:10,spacing:10,items:[(t=e,{type:"container",html:'
'+M(t)+"
",flex:1}),{type:"container",html:'

'+C.translate("Premium plugins:")+'

  • PowerPaste
  • Spell Checker Pro
  • Accessibility Checker
  • Advanced Code Editor
  • Enhanced Media Embed
  • Link Checker

'+C.translate("Learn more...")+"

",flex:1}]};var t},I=tinymce.util.Tools.resolve("tinymce.EditorManager"),j=function(){var e,t,n='TinyMCE '+(e=I.majorVersion,t=I.minorVersion,0===e.indexOf("@")?"X.X.X":e+"."+t)+"";return[{type:"label",html:C.translate(["You are using {0}",n])},{type:"spacer",flex:1},{text:"Close",onclick:function(){this.parent().parent().close()}}]},L=function(e,t){return function(){e.windowManager.open({title:"Help",bodyType:"tabpanel",layout:"flex",body:[T(),E(e)],buttons:j(),onPostRender:function(){this.getEl("title").innerHTML='TinyMCE Logo'}})}},B=function(e,t){e.addCommand("mceHelp",L(e,t))},N=function(e,t){e.addButton("help",{icon:"help",onclick:L(e,t)}),e.addMenuItem("help",{text:"Help",icon:"help",context:"help",onclick:L(e,t)})};e.add("help",function(e,t){N(e,t),B(e,t),e.shortcuts.add("Alt+0","Open help dialog","mceHelp")})}(); \ No newline at end of file +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(){},a=function(e){return function(){return e}};function l(r){for(var o=[],e=1;e'+v.translate(e.action)+""+e.shortcut+"";var t}).join("");return{title:"Handy Shortcuts",type:"container",style:"overflow-y: auto; overflow-x: hidden; max-height: 250px",items:[{type:"container",html:'
"+e+"
'+v.translate("Action")+""+v.translate("Shortcut")+"
"}]}},S=Object.keys,O=[{key:"advlist",name:"Advanced List"},{key:"anchor",name:"Anchor"},{key:"autolink",name:"Autolink"},{key:"autoresize",name:"Autoresize"},{key:"autosave",name:"Autosave"},{key:"bbcode",name:"BBCode"},{key:"charmap",name:"Character Map"},{key:"code",name:"Code"},{key:"codesample",name:"Code Sample"},{key:"colorpicker",name:"Color Picker"},{key:"compat3x",name:"3.x Compatibility"},{key:"contextmenu",name:"Context Menu"},{key:"directionality",name:"Directionality"},{key:"emoticons",name:"Emoticons"},{key:"fullpage",name:"Full Page"},{key:"fullscreen",name:"Full Screen"},{key:"help",name:"Help"},{key:"hr",name:"Horizontal Rule"},{key:"image",name:"Image"},{key:"imagetools",name:"Image Tools"},{key:"importcss",name:"Import CSS"},{key:"insertdatetime",name:"Insert Date/Time"},{key:"legacyoutput",name:"Legacy Output"},{key:"link",name:"Link"},{key:"lists",name:"Lists"},{key:"media",name:"Media"},{key:"nonbreaking",name:"Nonbreaking"},{key:"noneditable",name:"Noneditable"},{key:"pagebreak",name:"Page Break"},{key:"paste",name:"Paste"},{key:"preview",name:"Preview"},{key:"print",name:"Print"},{key:"save",name:"Save"},{key:"searchreplace",name:"Search and Replace"},{key:"spellchecker",name:"Spell Checker"},{key:"tabfocus",name:"Tab Focus"},{key:"table",name:"Table"},{key:"template",name:"Template"},{key:"textcolor",name:"Text Color"},{key:"textpattern",name:"Text Pattern"},{key:"toc",name:"Table of Contents"},{key:"visualblocks",name:"Visual Blocks"},{key:"visualchars",name:"Visual Characters"},{key:"wordcount",name:"Word Count"}],T=l(function(e,o){return e.replace(/\$\{([^{}]*)\}/g,function(e,t){var n,r=o[t];return"string"==(n=typeof r)||"number"===n?r.toString():e})},'${name}'),P=function(t,n){return function(e,t){for(var n=0,r=e.length;n"+P(t,e)+""}),i=a.length,c=a.join("");return"

"+v.translate(["Plugins installed ({0}):",i])+"

    "+c+"
"},H=function(e){return{title:"Plugins",type:"container",style:"overflow-y: auto; overflow-x: hidden;",layout:"flex",padding:10,spacing:10,items:[(t=e,{type:"container",html:'
'+_(t)+"
",flex:1}),{type:"container",html:'

'+v.translate("Premium plugins:")+'

  • PowerPaste
  • Spell Checker Pro
  • Accessibility Checker
  • Advanced Code Editor
  • Enhanced Media Embed
  • Link Checker

'+v.translate("Learn more...")+"

",flex:1}]};var t},F=tinymce.util.Tools.resolve("tinymce.EditorManager"),M=function(){var e,t,n='TinyMCE '+(e=F.majorVersion,t=F.minorVersion,0===e.indexOf("@")?"X.X.X":e+"."+t)+"";return[{type:"label",html:v.translate(["You are using {0}",n])},{type:"spacer",flex:1},{text:"Close",onclick:function(){this.parent().parent().close()}}]},E=function(e,t){return function(){e.windowManager.open({title:"Help",bodyType:"tabpanel",layout:"flex",body:[w(),H(e)],buttons:M(),onPostRender:function(){this.getEl("title").innerHTML='TinyMCE Logo'}})}},I=function(e,t){e.addCommand("mceHelp",E(e,t))},j=function(e,t){e.addButton("help",{icon:"help",onclick:E(e,t)}),e.addMenuItem("help",{text:"Help",icon:"help",context:"help",onclick:E(e,t)})};e.add("help",function(e,t){j(e,t),I(e,t),e.shortcuts.add("Alt+0","Open help dialog","mceHelp")})}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/image/plugin.min.js b/public/libs/tinymce/plugins/image/plugin.min.js index d4764ad62..23473aa76 100644 --- a/public/libs/tinymce/plugins/image/plugin.min.js +++ b/public/libs/tinymce/plugins/image/plugin.min.js @@ -1 +1 @@ -!function(l){"use strict";var i,e=tinymce.util.Tools.resolve("tinymce.PluginManager"),d=function(e){return!1!==e.settings.image_dimensions},u=function(e){return!0===e.settings.image_advtab},m=function(e){return e.getParam("image_prepend_url","")},n=function(e){return e.getParam("image_class_list")},r=function(e){return!1!==e.settings.image_description},a=function(e){return!0===e.settings.image_title},o=function(e){return!0===e.settings.image_caption},c=function(e){return e.getParam("image_list",!1)},s=function(e){return e.getParam("images_upload_url",!1)},g=function(e){return e.getParam("images_upload_handler",!1)},f=function(e){return e.getParam("images_upload_url")},p=function(e){return e.getParam("images_upload_handler")},h=function(e){return e.getParam("images_upload_base_path")},v=function(e){return e.getParam("images_upload_credentials")},b="undefined"!=typeof l.window?l.window:Function("return this;")(),y=function(e,t){return function(e,t){for(var n=t!==undefined&&null!==t?t:b,r=0;rthis.length())return null;for(var n=this.littleEndian?0:-8*(e-1),r=0,o=0;r=s.length())throw new Error("Invalid Exif data.");"ASCII"!==i?(f=s.asArray(i,c,a),l=1==a?f[0]:f,at.hasOwnProperty(o)&&"object"!=typeof l?d[o]=at[o][l]:d[o]=l):d[o]=s.STRING(c,a).replace(/\0$/,"").trim()}return d},t}(),ct=function(t){var e,n,r=[],o=0;for(e=2;e<=t.length();)if(65488<=(n=t.SHORT(e))&&n<=65495)e+=2;else{if(65498===n||65497===n)break;o=t.SHORT(e+2)+2,65505<=n&&n<=65519&&r.push({hex:n,name:"APP"+(15&n),start:e,length:o,segment:t.SEGMENT(e,o)}),e+=o}return r},lt=function(u){return L.blobToArrayBuffer(u).then(function(t){try{var e=new et(t);if(65496===e.SHORT(0)){var n=ct(e),r=n.filter(function(t){return"APP1"===t.name}),o={};if(!r.length)return g.reject("Headers did not include required information");var i=new ut(r[0].segment);return(o={tiff:i.TIFF(),exif:i.EXIF(),gps:i.GPS(),thumb:i.thumb()}).rawHeaders=n,o}return g.reject("Image was not a jpeg")}catch(a){return g.reject("Unsupported format or not an image: "+u.type+" (Exception: "+a.message+")")}})},st=function(t,e){return tt.rotate(t,e)},ft={invert:function(t){return Z.invert(t)},sharpen:function(t){return Z.sharpen(t)},emboss:function(t){return Z.emboss(t)},brightness:function(t,e){return Z.brightness(t,e)},hue:function(t,e){return Z.hue(t,e)},saturate:function(t,e){return Z.saturate(t,e)},contrast:function(t,e){return Z.contrast(t,e)},grayscale:function(t,e){return Z.grayscale(t,e)},sepia:function(t,e){return Z.sepia(t,e)},colorize:function(t,e,n,r){return Z.colorize(t,e,n,r)},gamma:function(t,e){return Z.gamma(t,e)},exposure:function(t,e){return Z.exposure(t,e)},flip:function(t,e){return tt.flip(t,e)},crop:function(t,e,n,r,o){return tt.crop(t,e,n,r,o)},resize:function(t,e,n){return tt.resize(t,e,n)},rotate:st,exifRotate:function(e){return e.toBlob().then(lt).then(function(t){switch(t.tiff.Orientation){case 6:return st(e,90);case 3:return st(e,180);case 8:return st(e,270);default:return e}},function(){return e})}},dt=function(t){return t.toBlob()},ht={blobToImageResult:function(t){return N.fromBlob(t)},fromBlobAndUrlSync:function(t,e){return N.fromBlobAndUrlSync(t,e)},imageToImageResult:function(t){return N.fromImage(t)},imageResultToBlob:function(t,e,n){return e===undefined&&n===undefined?dt(t):t.toAdjustedBlob(e,n)},imageResultToOriginalBlob:dt,imageResultToDataURL:function(t){return t.toDataURL()}},pt=function(){return O.getOrDie("URL")},gt={createObjectURL:function(t){return pt().createObjectURL(t)},revokeObjectURL:function(t){pt().revokeObjectURL(t)}},mt=tinymce.util.Tools.resolve("tinymce.util.Delay"),yt=tinymce.util.Tools.resolve("tinymce.util.Promise"),vt=tinymce.util.Tools.resolve("tinymce.util.URI"),bt=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),wt=tinymce.util.Tools.resolve("tinymce.ui.Factory"),xt=tinymce.util.Tools.resolve("tinymce.geom.Rect"),It=function(n){return new yt(function(t){var e=function(){n.removeEventListener("load",e),t(n)};n.complete?t(n):n.addEventListener("load",e)})},Tt=tinymce.util.Tools.resolve("tinymce.dom.DomQuery"),Rt=tinymce.util.Tools.resolve("tinymce.util.Observable"),St=tinymce.util.Tools.resolve("tinymce.util.VK"),Ot=0,Ft={create:function(t){return new(wt.get("Control").extend({Defaults:{classes:"imagepanel"},selection:function(t){return arguments.length?(this.state.set("rect",t),this):this.state.get("rect")},imageSize:function(){var t=this.state.get("viewRect");return{w:t.w,h:t.h}},toggleCropRect:function(t){this.state.set("cropEnabled",t)},imageSrc:function(t){var o=this,i=new s.Image;i.src=t,It(i).then(function(){var t,e,n=o.state.get("viewRect");if((e=o.$el.find("img"))[0])e.replaceWith(i);else{var r=s.document.createElement("div");r.className="mce-imagepanel-bg",o.getEl().appendChild(r),o.getEl().appendChild(i)}t={x:0,y:0,w:i.naturalWidth,h:i.naturalHeight},o.state.set("viewRect",t),o.state.set("rect",xt.inflate(t,-20,-20)),n&&n.w===t.w&&n.h===t.h||o.zoomFit(),o.repaintImage(),o.fire("load")})},zoom:function(t){return arguments.length?(this.state.set("zoom",t),this):this.state.get("zoom")},postRender:function(){return this.imageSrc(this.settings.imageSrc),this._super()},zoomFit:function(){var t,e,n,r,o,i;t=this.$el.find("img"),e=this.getEl().clientWidth,n=this.getEl().clientHeight,r=t[0].naturalWidth,o=t[0].naturalHeight,1<=(i=Math.min((e-10)/r,(n-10)/o))&&(i=1),this.zoom(i)},repaintImage:function(){var t,e,n,r,o,i,a,u,c,l,s;s=this.getEl(),c=this.zoom(),l=this.state.get("rect"),a=this.$el.find("img"),u=this.$el.find(".mce-imagepanel-bg"),o=s.offsetWidth,i=s.offsetHeight,n=a[0].naturalWidth*c,r=a[0].naturalHeight*c,t=Math.max(0,o/2-n/2),e=Math.max(0,i/2-r/2),a.css({left:t,top:e,width:n,height:r}),u.css({left:t,top:e,width:n,height:r}),this.cropRect&&(this.cropRect.setRect({x:l.x*c+t,y:l.y*c+e,w:l.w*c,h:l.h*c}),this.cropRect.setClampRect({x:t,y:e,w:n,h:r}),this.cropRect.setViewPortRect({x:0,y:0,w:o,h:i}))},bindStates:function(){var r=this;function n(t){r.cropRect=function(l,n,s,r,o){var f,a,t,i,e="mce-",u=e+"crid-"+Ot++;function d(t,e){return{x:e.x-t.x,y:e.y-t.y,w:e.w,h:e.h}}function c(t,e,n,r){var o,i,a,u,c;o=e.x,i=e.y,a=e.w,u=e.h,o+=n*t.deltaX,i+=r*t.deltaY,(a+=n*t.deltaW)<20&&(a=20),(u+=r*t.deltaH)<20&&(u=20),c=l=xt.clamp({x:o,y:i,w:a,h:u},s,"move"===t.name),c=d(s,c),f.fire("updateRect",{rect:c}),g(c)}function h(e){function t(t,e){e.h<0&&(e.h=0),e.w<0&&(e.w=0),Tt("#"+u+"-"+t,r).css({left:e.x,top:e.y,width:e.w,height:e.h})}$.each(a,function(t){Tt("#"+u+"-"+t.name,r).css({left:e.w*t.xMul+e.x,top:e.h*t.yMul+e.y})}),t("top",{x:n.x,y:n.y,w:n.w,h:e.y-n.y}),t("right",{x:e.x+e.w,y:e.y,w:n.w-e.x-e.w+n.x,h:e.h}),t("bottom",{x:n.x,y:e.y+e.h,w:n.w,h:n.h-e.y-e.h+n.y}),t("left",{x:n.x,y:e.y,w:e.x-n.x,h:e.h}),t("move",e)}function p(t){h(l=t)}function g(t){var e,n;p((e=s,{x:(n=t).x+e.x,y:n.y+e.y,w:n.w,h:n.h}))}return a=[{name:"move",xMul:0,yMul:0,deltaX:1,deltaY:1,deltaW:0,deltaH:0,label:"Crop Mask"},{name:"nw",xMul:0,yMul:0,deltaX:1,deltaY:1,deltaW:-1,deltaH:-1,label:"Top Left Crop Handle"},{name:"ne",xMul:1,yMul:0,deltaX:0,deltaY:1,deltaW:1,deltaH:-1,label:"Top Right Crop Handle"},{name:"sw",xMul:0,yMul:1,deltaX:1,deltaY:0,deltaW:-1,deltaH:1,label:"Bottom Left Crop Handle"},{name:"se",xMul:1,yMul:1,deltaX:0,deltaY:0,deltaW:1,deltaH:1,label:"Bottom Right Crop Handle"}],i=["top","right","bottom","left"],Tt('
').appendTo(r),$.each(i,function(t){Tt("#"+u,r).append('
From d4b0e4acad815d48e59eb0cde286340db8a95d30 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 11 Apr 2020 20:02:07 +0100 Subject: [PATCH 030/197] Removed throttling from web-end requests Generally seems to cause issues when secure images are in use. Was added during laravel upgrade but laravel does not use this directly for its web middleware anyway. --- app/Http/Kernel.php | 1 - resources/sass/_forms.scss | 2 +- resources/sass/_header.scss | 5 +++-- resources/sass/_lists.scss | 3 ++- resources/sass/_pages.scss | 14 ++++++++++---- resources/sass/styles.scss | 5 +++++ 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 4517deb90..a0c45ea89 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -26,7 +26,6 @@ class Kernel extends HttpKernel \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, - \Illuminate\Routing\Middleware\ThrottleRequests::class, \BookStack\Http\Middleware\VerifyCsrfToken::class, \BookStack\Http\Middleware\Localization::class, \BookStack\Http\Middleware\GlobalViewData::class, diff --git a/resources/sass/_forms.scss b/resources/sass/_forms.scss index 824c229bd..32d873642 100644 --- a/resources/sass/_forms.scss +++ b/resources/sass/_forms.scss @@ -385,7 +385,7 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] { button { background-color: transparent; border: none; - fill: #666; + @include lightDark(color, #666, #AAA); padding: 0; cursor: pointer; position: absolute; diff --git a/resources/sass/_header.scss b/resources/sass/_header.scss index 1c4bf948f..e0a8ad1a4 100644 --- a/resources/sass/_header.scss +++ b/resources/sass/_header.scss @@ -98,6 +98,7 @@ header .search-box { button { z-index: 1; left: 16px; + @include lightDark(color, rgba(255, 255, 255, 0.8), #AAA); @include rtl { left: auto; right: 16px; @@ -264,7 +265,7 @@ header .search-box { display: none; } > span:first-child { - margin-block-end: 0; + margin-inline-end: 0; } } } @@ -280,7 +281,7 @@ header .search-box { } } .svg-icon { - margin-block-end: 0; + margin-inline-end: 0; } } diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 9324bbf7b..8165d532d 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -358,7 +358,8 @@ ul.pagination { } } li.active span { - color: #FFF; + @include lightDark(color, #444, #eee); + @include lightDark(background-color, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.5)); } } diff --git a/resources/sass/_pages.scss b/resources/sass/_pages.scss index 1833a0c6e..1ed02d2e7 100755 --- a/resources/sass/_pages.scss +++ b/resources/sass/_pages.scss @@ -151,15 +151,16 @@ body.mce-fullscreen, body.markdown-fullscreen { } .pointer { border: 1px solid #CCC; + @include lightDark(border-color, #ccc, #000); display: flex; align-items: center; justify-items: center; padding: $-s $-s; border-radius: 4px; - box-shadow: 0 0 12px 1px rgba(212, 209, 209, 0.3); + box-shadow: 0 0 12px 1px rgba(0, 0, 0, 0.1); position: absolute; top: -60px; - background-color:#FFF; + @include lightDark(background-color, #fff, #333); width: 275px; z-index: 55; @@ -176,12 +177,13 @@ body.mce-fullscreen, body.markdown-fullscreen { margin-inline-start: -8px; content: ''; display: block; - background-color:#FFF; transform: rotate(45deg); transform-origin: 50% 50%; - border-inline-startom: 1px solid #CCC; + border-block-end: 1px solid #CCC; border-inline-end: 1px solid #CCC; z-index: 56; + @include lightDark(background-color, #fff, #333); + @include lightDark(border-color, #ccc, #000); } input, button, a { position: relative; @@ -194,6 +196,7 @@ body.mce-fullscreen, body.markdown-fullscreen { input { background-color: #FFF; border: 1px solid #DDD; + @include lightDark(border-color, #ddd, #000); color: #666; width: 172px; z-index: 40; @@ -218,6 +221,9 @@ body.mce-fullscreen, body.markdown-fullscreen { width: 1.2em; height: 1.2em; } + .button { + @include lightDark(border-color, #ddd, #000); + } } // Attribute form diff --git a/resources/sass/styles.scss b/resources/sass/styles.scss index 1a9d793b6..8af363469 100644 --- a/resources/sass/styles.scss +++ b/resources/sass/styles.scss @@ -54,6 +54,11 @@ body.dragging, body.dragging * { &.square { border-radius: 3px; } + &[src$="user_avatar.png"] { + @include whenDark { + filter: invert(1); + } + } } // Loading icon From 573c848d510ef7f1b959b20eb8a6bf4c167a856b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 11 Apr 2020 20:37:51 +0100 Subject: [PATCH 031/197] Added dark/light mode toggle to profile dropdown menu - Also fixed some remaining areas which needed dark mode support. --- app/Http/Controllers/UserController.php | 10 ++++++++++ resources/icons/dark-mode.svg | 1 + resources/icons/light-mode.svg | 1 + resources/sass/_lists.scss | 3 +++ resources/views/base.blade.php | 10 +++------- resources/views/common/header.blade.php | 12 ++++++++++++ routes/web.php | 1 + 7 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 resources/icons/dark-mode.svg create mode 100644 resources/icons/light-mode.svg diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 43cbad1fb..775e2a984 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -312,6 +312,16 @@ class UserController extends Controller return $this->changeListSort($id, $request, $type); } + /** + * Toggle dark mode for the current user. + */ + public function toggleDarkMode() + { + $enabled = setting()->getForCurrentUser('dark-mode-enabled', false); + setting()->putUser(user(), 'dark-mode-enabled', $enabled ? 'false' : 'true'); + return redirect()->back(); + } + /** * Update the stored section expansion preference for the given user. */ diff --git a/resources/icons/dark-mode.svg b/resources/icons/dark-mode.svg new file mode 100644 index 000000000..8b00d72a5 --- /dev/null +++ b/resources/icons/dark-mode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/light-mode.svg b/resources/icons/light-mode.svg new file mode 100644 index 000000000..cf2961d2e --- /dev/null +++ b/resources/icons/light-mode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 8165d532d..5eb672697 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -603,6 +603,9 @@ ul.pagination { li.border-bottom { border-bottom: 1px solid #DDD; } + li hr { + margin: $-xs 0; + } } // Books grid view diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index 0f43532fb..a5404a365 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -1,5 +1,7 @@ - + {{ isset($pageTitle) ? $pageTitle . ' | ' : '' }}{{ setting('app-name') }} @@ -23,12 +25,6 @@ @stack('translations') - - diff --git a/resources/views/common/header.blade.php b/resources/views/common/header.blade.php index ec90739ee..af7aaeeb0 100644 --- a/resources/views/common/header.blade.php +++ b/resources/views/common/header.blade.php @@ -70,6 +70,18 @@ @icon('logout'){{ trans('auth.logout') }} @endif +

  • +
  • +
    + {{ csrf_field() }} + {{ method_field('patch') }} + @if(setting()->getForCurrentUser('dark-mode-enabled')) + + @else + + @endif +
    +
  • @endif diff --git a/routes/web.php b/routes/web.php index 4dfccdf36..3e05e394d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -183,6 +183,7 @@ Route::group(['middleware' => 'auth'], function () { Route::patch('/users/{id}/switch-shelf-view', 'UserController@switchShelfView'); Route::patch('/users/{id}/change-sort/{type}', 'UserController@changeSort'); Route::patch('/users/{id}/update-expansion-preference/{key}', 'UserController@updateExpansionPreference'); + Route::patch('/users/toggle-dark-mode', 'UserController@toggleDarkMode'); Route::post('/users/create', 'UserController@store'); Route::get('/users/{id}', 'UserController@edit'); Route::put('/users/{id}', 'UserController@update'); From 50669e3f4a32eff3523b703886e523ed84470583 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 11 Apr 2020 20:44:23 +0100 Subject: [PATCH 032/197] Added tests and translations for dark-mode components --- resources/lang/en/common.php | 2 ++ resources/views/common/header.blade.php | 4 ++-- tests/User/UserPreferencesTest.php | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php index c8b4a2b22..68c58b92b 100644 --- a/resources/lang/en/common.php +++ b/resources/lang/en/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profile Menu', 'view_profile' => 'View Profile', 'edit_profile' => 'Edit Profile', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/views/common/header.blade.php b/resources/views/common/header.blade.php index af7aaeeb0..98bd01788 100644 --- a/resources/views/common/header.blade.php +++ b/resources/views/common/header.blade.php @@ -76,9 +76,9 @@ {{ csrf_field() }} {{ method_field('patch') }} @if(setting()->getForCurrentUser('dark-mode-enabled')) - + @else - + @endif diff --git a/tests/User/UserPreferencesTest.php b/tests/User/UserPreferencesTest.php index b70d52dfa..0db4f803a 100644 --- a/tests/User/UserPreferencesTest.php +++ b/tests/User/UserPreferencesTest.php @@ -75,4 +75,21 @@ class UserPreferencesTest extends TestCase $invalidKeyRequest = $this->patch('/settings/users/' . $editor->id.'/update-expansion-preference/my-home-details', ['expand' => 'true']); $invalidKeyRequest->assertStatus(500); } + + public function test_toggle_dark_mode() + { + $home = $this->actingAs($this->getEditor())->get('/'); + $home->assertElementNotExists('.dark-mode'); + $home->assertSee('Dark Mode'); + + $this->assertEquals(false, setting()->getForCurrentUser('dark-mode-enabled', false)); + $prefChange = $this->patch('/settings/users/toggle-dark-mode'); + $prefChange->assertRedirect(); + $this->assertEquals(true, setting()->getForCurrentUser('dark-mode-enabled')); + + $home = $this->actingAs($this->getEditor())->get('/'); + $home->assertElementExists('.dark-mode'); + $home->assertDontSee('Dark Mode'); + $home->assertSee('Light Mode'); + } } \ No newline at end of file From 88dfb40c630ac5f6bb3548092adfeca3fa2f3fbd Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 12 Apr 2020 19:06:34 +0100 Subject: [PATCH 033/197] Some further dark-mode fixes, added toggle to homepage - Homepage toggle especially useful for not-logged-in users since they do not have a dropdown. --- resources/sass/_header.scss | 11 +++++------ resources/sass/_lists.scss | 2 ++ resources/views/common/header.blade.php | 10 +--------- resources/views/common/home-book.blade.php | 1 + resources/views/common/home-custom.blade.php | 1 + resources/views/common/home-shelves.blade.php | 1 + resources/views/common/home.blade.php | 13 +++++++++++-- resources/views/partials/dark-mode-toggle.blade.php | 9 +++++++++ 8 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 resources/views/partials/dark-mode-toggle.blade.php diff --git a/resources/sass/_header.scss b/resources/sass/_header.scss index e0a8ad1a4..4c3f6c619 100644 --- a/resources/sass/_header.scss +++ b/resources/sass/_header.scss @@ -167,8 +167,8 @@ header .search-box { @include smaller-than($l) { header .header-links { + @include lightDark(background-color, #fff, #333); display: none; - background-color: #FFF; z-index: 10; right: $-m; border-radius: 4px; @@ -180,19 +180,18 @@ header .search-box { display: block; } } - header .links a, header .dropdown-container ul li a { + header .links a, header .dropdown-container ul li a, header .dropdown-container ul li button { text-align: start; display: block; padding: $-s $-m; color: $text-dark; - fill: $text-dark; + @include lightDark(color, $text-dark, #eee); svg { margin-inline-end: $-s; } &:hover { - background-color: #EEE; - color: #444; - fill: #444; + @include lightDark(background-color, #eee, #333); + @include lightDark(color, #000, #fff); text-decoration: none; } } diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 5eb672697..32c56f385 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -581,6 +581,8 @@ ul.pagination { @include lightDark(color, #555, #eee); fill: currentColor; white-space: nowrap; + line-height: 1.6; + cursor: pointer; &:hover, &:focus { text-decoration: none; background-color: var(--color-primary-light); diff --git a/resources/views/common/header.blade.php b/resources/views/common/header.blade.php index 98bd01788..4937f7cb0 100644 --- a/resources/views/common/header.blade.php +++ b/resources/views/common/header.blade.php @@ -72,15 +72,7 @@

  • -
    - {{ csrf_field() }} - {{ method_field('patch') }} - @if(setting()->getForCurrentUser('dark-mode-enabled')) - - @else - - @endif -
    + @include('partials.dark-mode-toggle')
  • diff --git a/resources/views/common/home-book.blade.php b/resources/views/common/home-book.blade.php index 8caae814a..3dbcd2875 100644 --- a/resources/views/common/home-book.blade.php +++ b/resources/views/common/home-book.blade.php @@ -14,6 +14,7 @@
    @include('partials.view-toggle', ['view' => $view, 'type' => 'books']) @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details']) + @include('partials.dark-mode-toggle', ['classes' => 'text-muted icon-list-item text-primary'])
    @stop \ No newline at end of file diff --git a/resources/views/common/home-custom.blade.php b/resources/views/common/home-custom.blade.php index 56e281dcb..e08203057 100644 --- a/resources/views/common/home-custom.blade.php +++ b/resources/views/common/home-custom.blade.php @@ -19,6 +19,7 @@
    {{ trans('common.actions') }}
    @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details']) + @include('partials.dark-mode-toggle', ['classes' => 'text-muted icon-list-item text-primary'])
    @stop \ No newline at end of file diff --git a/resources/views/common/home-shelves.blade.php b/resources/views/common/home-shelves.blade.php index bac6fa154..fccbef288 100644 --- a/resources/views/common/home-shelves.blade.php +++ b/resources/views/common/home-shelves.blade.php @@ -14,6 +14,7 @@
    @include('partials.view-toggle', ['view' => $view, 'type' => 'shelves']) @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details']) + @include('partials.dark-mode-toggle', ['classes' => 'text-muted icon-list-item text-primary'])
    @stop \ No newline at end of file diff --git a/resources/views/common/home.blade.php b/resources/views/common/home.blade.php index cd27ff568..63b76aa10 100644 --- a/resources/views/common/home.blade.php +++ b/resources/views/common/home.blade.php @@ -3,8 +3,17 @@ @section('body')
    -
    - @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details']) +
    +
    +
    + @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details']) +
    +
    +
    +
    + @include('partials.dark-mode-toggle', ['classes' => 'text-muted icon-list-item text-primary']) +
    +
    diff --git a/resources/views/partials/dark-mode-toggle.blade.php b/resources/views/partials/dark-mode-toggle.blade.php new file mode 100644 index 000000000..0812e487a --- /dev/null +++ b/resources/views/partials/dark-mode-toggle.blade.php @@ -0,0 +1,9 @@ +
    + {{ csrf_field() }} + {{ method_field('patch') }} + @if(setting()->getForCurrentUser('dark-mode-enabled')) + + @else + + @endif +
    \ No newline at end of file From 687c4247ae4d31ff3eaca7af814afb019d14c834 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 13 Apr 2020 15:31:35 +0100 Subject: [PATCH 034/197] New Crowdin translations (#2005) * New translations settings.php (Portuguese) * New translations settings.php (Portuguese, Brazilian) * New translations settings.php (Russian) * New translations settings.php (Korean) * New translations settings.php (Persian) * New translations settings.php (Polish) * New translations settings.php (Swedish) * New translations settings.php (Spanish, Argentina) * New translations settings.php (Turkish) * New translations settings.php (Slovak) * New translations settings.php (Slovenian) * New translations settings.php (Spanish) * New translations settings.php (Czech) * New translations settings.php (Danish) * New translations settings.php (Dutch) * New translations settings.php (Arabic) * New translations settings.php (Chinese Simplified) * New translations settings.php (Chinese Traditional) * New translations settings.php (Italian) * New translations settings.php (Hungarian) * New translations settings.php (Japanese) * New translations settings.php (French) * New translations settings.php (German) * New translations settings.php (Hebrew) * New translations settings.php (German Informal) * New translations settings.php (Vietnamese) * New translations settings.php (Ukrainian) * New translations activities.php (Turkish) * New translations activities.php (Turkish) * New translations auth.php (Turkish) * New translations common.php (Turkish) * New translations auth.php (Turkish) * New translations components.php (Turkish) * New translations common.php (Turkish) * New translations components.php (Turkish) * New translations entities.php (Turkish) * New translations entities.php (Turkish) * New translations errors.php (Turkish) * New translations entities.php (Turkish) * New translations passwords.php (Turkish) * New translations settings.php (Turkish) * New translations errors.php (Turkish) * New translations settings.php (Turkish) * New translations settings.php (Turkish) * New translations validation.php (Turkish) * New translations settings.php (Turkish) * New translations validation.php (Turkish) * New translations common.php (Turkish) * New translations components.php (Turkish) * New translations validation.php (Turkish) * New translations components.php (Turkish) * New translations entities.php (Turkish) * New translations errors.php (Turkish) * New translations settings.php (Turkish) * New translations validation.php (Turkish) * New translations passwords.php (Arabic) * New translations auth.php (Arabic) * New translations auth.php (Slovak) * New translations passwords.php (Russian) * New translations passwords.php (Slovak) * New translations auth.php (Slovenian) * New translations passwords.php (Slovenian) * New translations auth.php (Spanish) * New translations passwords.php (Portuguese, Brazilian) * New translations passwords.php (Polish) * New translations auth.php (Portuguese) * New translations auth.php (Russian) * New translations passwords.php (Portuguese) * New translations auth.php (Portuguese, Brazilian) * New translations auth.php (Ukrainian) * New translations passwords.php (Ukrainian) * New translations auth.php (Vietnamese) * New translations passwords.php (Vietnamese) * New translations auth.php (German Informal) * New translations passwords.php (German Informal) * New translations passwords.php (Turkish) * New translations passwords.php (Spanish) * New translations auth.php (Spanish, Argentina) * New translations passwords.php (Spanish, Argentina) * New translations auth.php (Swedish) * New translations passwords.php (Swedish) * New translations auth.php (Turkish) * New translations components.php (Turkish) * New translations entities.php (Turkish) * New translations auth.php (Polish) * New translations passwords.php (Danish) * New translations auth.php (Dutch) * New translations passwords.php (Dutch) * New translations auth.php (Danish) * New translations auth.php (French) * New translations passwords.php (French) * New translations auth.php (Chinese Simplified) * New translations passwords.php (Chinese Simplified) * New translations auth.php (Chinese Traditional) * New translations passwords.php (Chinese Traditional) * New translations auth.php (Czech) * New translations passwords.php (Czech) * New translations auth.php (German) * New translations auth.php (Korean) * New translations auth.php (Japanese) * New translations passwords.php (Japanese) * New translations passwords.php (Korean) * New translations auth.php (Persian) * New translations passwords.php (Persian) * New translations passwords.php (Italian) * New translations passwords.php (German) * New translations auth.php (Hebrew) * New translations passwords.php (Hebrew) * New translations auth.php (Hungarian) * New translations passwords.php (Hungarian) * New translations auth.php (Italian) * New translations entities.php (Turkish) * New translations settings.php (Turkish) * New translations validation.php (Turkish) * New translations passwords.php (Turkish) * New translations entities.php (Turkish) * New translations errors.php (Turkish) * New translations validation.php (Turkish) * New translations auth.php (Turkish) * New translations auth.php (Spanish) * New translations passwords.php (Spanish) * New translations settings.php (Spanish) * New translations auth.php (Spanish, Argentina) * New translations passwords.php (Spanish, Argentina) * New translations entities.php (Turkish) * New translations auth.php (French) * New translations passwords.php (French) * New translations settings.php (French) * New translations common.php (Russian) * New translations common.php (Slovak) * New translations common.php (Slovenian) * New translations common.php (Spanish) * New translations common.php (Portuguese) * New translations common.php (Polish) * New translations common.php (Portuguese, Brazilian) * New translations common.php (Ukrainian) * New translations common.php (Vietnamese) * New translations common.php (German Informal) * New translations common.php (Spanish, Argentina) * New translations common.php (Swedish) * New translations common.php (Turkish) * New translations common.php (Danish) * New translations common.php (Dutch) * New translations common.php (French) * New translations common.php (Arabic) * New translations common.php (Chinese Simplified) * New translations common.php (Czech) * New translations common.php (Chinese Traditional) * New translations common.php (Japanese) * New translations common.php (Italian) * New translations common.php (Korean) * New translations common.php (Persian) * New translations common.php (German) * New translations common.php (Hebrew) * New translations common.php (Hungarian) * New translations auth.php (Russian) * New translations common.php (Russian) * New translations passwords.php (Russian) * New translations passwords.php (German) * New translations settings.php (German) * New translations auth.php (German) * New translations common.php (German) * New translations settings.php (German Informal) * New translations passwords.php (German Informal) * New translations common.php (German Informal) * New translations auth.php (German Informal) --- resources/lang/ar/auth.php | 2 +- resources/lang/ar/common.php | 2 + resources/lang/ar/passwords.php | 2 +- resources/lang/ar/settings.php | 1 + resources/lang/cs/auth.php | 2 +- resources/lang/cs/common.php | 2 + resources/lang/cs/passwords.php | 2 +- resources/lang/cs/settings.php | 1 + resources/lang/da/auth.php | 2 +- resources/lang/da/common.php | 2 + resources/lang/da/passwords.php | 2 +- resources/lang/da/settings.php | 1 + resources/lang/de/auth.php | 2 +- resources/lang/de/common.php | 2 + resources/lang/de/passwords.php | 2 +- resources/lang/de/settings.php | 1 + resources/lang/de_informal/auth.php | 2 +- resources/lang/de_informal/common.php | 2 + resources/lang/de_informal/passwords.php | 2 +- resources/lang/de_informal/settings.php | 1 + resources/lang/es/auth.php | 2 +- resources/lang/es/common.php | 2 + resources/lang/es/passwords.php | 2 +- resources/lang/es/settings.php | 3 +- resources/lang/es_AR/auth.php | 2 +- resources/lang/es_AR/common.php | 2 + resources/lang/es_AR/passwords.php | 2 +- resources/lang/es_AR/settings.php | 1 + resources/lang/fa/auth.php | 2 +- resources/lang/fa/common.php | 2 + resources/lang/fa/passwords.php | 2 +- resources/lang/fa/settings.php | 1 + resources/lang/fr/auth.php | 2 +- resources/lang/fr/common.php | 2 + resources/lang/fr/passwords.php | 2 +- resources/lang/fr/settings.php | 1 + resources/lang/he/auth.php | 2 +- resources/lang/he/common.php | 2 + resources/lang/he/passwords.php | 2 +- resources/lang/he/settings.php | 1 + resources/lang/hu/auth.php | 2 +- resources/lang/hu/common.php | 2 + resources/lang/hu/passwords.php | 2 +- resources/lang/hu/settings.php | 1 + resources/lang/it/auth.php | 2 +- resources/lang/it/common.php | 2 + resources/lang/it/passwords.php | 2 +- resources/lang/it/settings.php | 1 + resources/lang/ja/auth.php | 2 +- resources/lang/ja/common.php | 2 + resources/lang/ja/passwords.php | 2 +- resources/lang/ja/settings.php | 1 + resources/lang/ko/auth.php | 2 +- resources/lang/ko/common.php | 2 + resources/lang/ko/passwords.php | 2 +- resources/lang/ko/settings.php | 1 + resources/lang/nl/auth.php | 2 +- resources/lang/nl/common.php | 2 + resources/lang/nl/passwords.php | 2 +- resources/lang/nl/settings.php | 1 + resources/lang/pl/auth.php | 2 +- resources/lang/pl/common.php | 2 + resources/lang/pl/passwords.php | 2 +- resources/lang/pl/settings.php | 1 + resources/lang/pt/auth.php | 2 +- resources/lang/pt/common.php | 2 + resources/lang/pt/passwords.php | 2 +- resources/lang/pt/settings.php | 1 + resources/lang/pt_BR/auth.php | 2 +- resources/lang/pt_BR/common.php | 2 + resources/lang/pt_BR/passwords.php | 2 +- resources/lang/pt_BR/settings.php | 1 + resources/lang/ru/auth.php | 2 +- resources/lang/ru/common.php | 2 + resources/lang/ru/passwords.php | 2 +- resources/lang/ru/settings.php | 1 + resources/lang/sk/auth.php | 2 +- resources/lang/sk/common.php | 2 + resources/lang/sk/passwords.php | 2 +- resources/lang/sk/settings.php | 1 + resources/lang/sl/auth.php | 2 +- resources/lang/sl/common.php | 2 + resources/lang/sl/passwords.php | 2 +- resources/lang/sl/settings.php | 1 + resources/lang/sv/auth.php | 2 +- resources/lang/sv/common.php | 2 + resources/lang/sv/passwords.php | 2 +- resources/lang/sv/settings.php | 1 + resources/lang/tr/activities.php | 34 ++-- resources/lang/tr/auth.php | 84 ++++----- resources/lang/tr/common.php | 32 ++-- resources/lang/tr/components.php | 22 +-- resources/lang/tr/entities.php | 230 +++++++++++------------ resources/lang/tr/errors.php | 88 ++++----- resources/lang/tr/passwords.php | 10 +- resources/lang/tr/settings.php | 166 ++++++++-------- resources/lang/tr/validation.php | 126 ++++++------- resources/lang/uk/auth.php | 2 +- resources/lang/uk/common.php | 2 + resources/lang/uk/passwords.php | 2 +- resources/lang/uk/settings.php | 1 + resources/lang/vi/auth.php | 2 +- resources/lang/vi/common.php | 2 + resources/lang/vi/passwords.php | 2 +- resources/lang/vi/settings.php | 1 + resources/lang/zh_CN/auth.php | 2 +- resources/lang/zh_CN/common.php | 2 + resources/lang/zh_CN/passwords.php | 2 +- resources/lang/zh_CN/settings.php | 1 + resources/lang/zh_TW/auth.php | 2 +- resources/lang/zh_TW/common.php | 2 + resources/lang/zh_TW/passwords.php | 2 +- resources/lang/zh_TW/settings.php | 1 + 113 files changed, 528 insertions(+), 448 deletions(-) diff --git a/resources/lang/ar/auth.php b/resources/lang/ar/auth.php index d9ed5cf27..afe089fa0 100644 --- a/resources/lang/ar/auth.php +++ b/resources/lang/ar/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'استعادة كلمة المرور', 'reset_password_send_instructions' => 'أدخل بريدك الإلكتروني بالأسفل وسيتم إرسال رسالة برابط لاستعادة كلمة المرور.', 'reset_password_send_button' => 'أرسل رابط الاستعادة', - 'reset_password_sent_success' => 'تم إرسال رابط استعادة كلمة المرور إلى :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'تمت استعادة كلمة المرور بنجاح.', 'email_reset_subject' => 'استعد كلمة المرور الخاصة بتطبيق :appName', 'email_reset_text' => 'تم إرسال هذه الرسالة بسبب تلقينا لطلب استعادة كلمة المرور الخاصة بحسابكم.', diff --git a/resources/lang/ar/common.php b/resources/lang/ar/common.php index 90c4e5159..193844390 100644 --- a/resources/lang/ar/common.php +++ b/resources/lang/ar/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profile Menu', 'view_profile' => 'عرض الملف الشخصي', 'edit_profile' => 'تعديل الملف الشخصي', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/ar/passwords.php b/resources/lang/ar/passwords.php index 23a8a7e74..db3dce49f 100644 --- a/resources/lang/ar/passwords.php +++ b/resources/lang/ar/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'يجب أن تتكون كلمة المرور من ستة أحرف على الأقل وأن تطابق التأكيد.', 'user' => "لم يتم العثور على مستخدم بعنوان البريد الإلكتروني المعطى.", - 'token' => 'رابط تجديد كلمة المرور غير صحيح.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'تم إرسال رابط تجديد كلمة المرور إلى بريدكم الإلكتروني!', 'reset' => 'تم تجديد كلمة المرور الخاصة بكم!', diff --git a/resources/lang/ar/settings.php b/resources/lang/ar/settings.php index 56b0a51be..0a689c5d5 100755 --- a/resources/lang/ar/settings.php +++ b/resources/lang/ar/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/cs/auth.php b/resources/lang/cs/auth.php index ff84f2ae9..0e841686d 100644 --- a/resources/lang/cs/auth.php +++ b/resources/lang/cs/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Resetovat heslo', 'reset_password_send_instructions' => 'Zadejte vaší emailovou adresu a bude vám zaslán odkaz na resetování hesla.', 'reset_password_send_button' => 'Poslat odkaz pro reset hesla', - 'reset_password_sent_success' => 'Odkaz na resetování hesla vám byl zaslán na :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Vaše heslo bylo úspěšně resetováno.', 'email_reset_subject' => 'Reset hesla do :appName', 'email_reset_text' => 'Tento email jste obdrželi, protože jsme dostali žádost o resetování vašeho hesla k účtu v :appName.', diff --git a/resources/lang/cs/common.php b/resources/lang/cs/common.php index 785648180..3586a6126 100644 --- a/resources/lang/cs/common.php +++ b/resources/lang/cs/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Nabídka profilu', 'view_profile' => 'Ukázat profil', 'edit_profile' => 'Upravit profil', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/cs/passwords.php b/resources/lang/cs/passwords.php index 020016330..368523630 100644 --- a/resources/lang/cs/passwords.php +++ b/resources/lang/cs/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Heslo musí být alespoň 6 znaků dlouhé a shodovat se v obou polích.', 'user' => "Nemůžeme najít uživatele se zadanou emailovou adresou.", - 'token' => 'Tento odkaz pro reset hesla je neplatný.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'Poslali jsme vám odkaz pro reset hesla!', 'reset' => 'Vaše heslo bylo resetováno!', diff --git a/resources/lang/cs/settings.php b/resources/lang/cs/settings.php index e36a53009..a5b60ba58 100644 --- a/resources/lang/cs/settings.php +++ b/resources/lang/cs/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/da/auth.php b/resources/lang/da/auth.php index 01c725ee6..a78f5c1c2 100644 --- a/resources/lang/da/auth.php +++ b/resources/lang/da/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Nulstil adgangskode', 'reset_password_send_instructions' => 'Indtast din E-Mail herunder og du vil blive sendt en E-Mail med et link til at nulstille din adgangskode.', 'reset_password_send_button' => 'Send link til nulstilling', - 'reset_password_sent_success' => 'Et link til at nulstille adgangskoden er blevet sendt til :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Din adgangskode er blevet nulstillet.', 'email_reset_subject' => 'Nulstil din :appName adgangskode', 'email_reset_text' => 'Du modtager denne E-Mail fordi vi har modtaget en anmodning om at nulstille din adgangskode.', diff --git a/resources/lang/da/common.php b/resources/lang/da/common.php index aaec2cc7a..008a9d24e 100644 --- a/resources/lang/da/common.php +++ b/resources/lang/da/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profilmenu', 'view_profile' => 'Vis profil', 'edit_profile' => 'Redigér Profil', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/da/passwords.php b/resources/lang/da/passwords.php index b4ace5513..035ccb2d1 100644 --- a/resources/lang/da/passwords.php +++ b/resources/lang/da/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Adgangskoder skal være mindst otte tegn og svare til bekræftelsen.', 'user' => "Vi kan ikke finde en bruger med den e-mail adresse.", - 'token' => 'Denne adgangskode nulstillingstoken er ugyldig.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'Vi har sendt dig en e-mail med et link til at nulstille adgangskoden!', 'reset' => 'Dit kodeord er blevet nulstillet!', diff --git a/resources/lang/da/settings.php b/resources/lang/da/settings.php index 8427d3722..b6f14a421 100644 --- a/resources/lang/da/settings.php +++ b/resources/lang/da/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/de/auth.php b/resources/lang/de/auth.php index 7216ffe48..1f5a49cbd 100644 --- a/resources/lang/de/auth.php +++ b/resources/lang/de/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Passwort vergessen', 'reset_password_send_instructions' => 'Bitte geben Sie Ihre E-Mail-Adresse ein. Danach erhalten Sie eine E-Mail mit einem Link zum Zurücksetzen Ihres Passwortes.', 'reset_password_send_button' => 'Passwort zurücksetzen', - 'reset_password_sent_success' => 'Eine E-Mail mit dem Link zum Zurücksetzen Ihres Passwortes wurde an :email gesendet.', + 'reset_password_sent' => 'Ein Link zum Zurücksetzen des Passworts wird an :email gesendet, wenn diese E-Mail-Adresse im System gefunden wird.', 'reset_password_success' => 'Ihr Passwort wurde erfolgreich zurückgesetzt.', 'email_reset_subject' => 'Passwort zurücksetzen für :appName', 'email_reset_text' => 'Sie erhalten diese E-Mail, weil jemand versucht hat, Ihr Passwort zurückzusetzen.', diff --git a/resources/lang/de/common.php b/resources/lang/de/common.php index 402e2b36d..5d0ad554a 100644 --- a/resources/lang/de/common.php +++ b/resources/lang/de/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profilmenü', 'view_profile' => 'Profil ansehen', 'edit_profile' => 'Profil bearbeiten', + 'dark_mode' => 'Dunkler Modus', + 'light_mode' => 'Heller Modus', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/de/passwords.php b/resources/lang/de/passwords.php index 74149a7ed..3da092cb8 100644 --- a/resources/lang/de/passwords.php +++ b/resources/lang/de/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Passwörter müssen aus mindestens sechs Zeichen bestehen und mit der eingegebenen Wiederholung übereinstimmen.', 'user' => "Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.", - 'token' => 'Dieser Link zum Zurücksetzen des Passwortes ist ungültig!', + 'token' => 'Der Link zum Zurücksetzen Ihres Passworts ist entweder ungültig oder abgelaufen.', 'sent' => 'Der Link zum Zurücksetzen Ihres Passwortes wurde Ihnen per E-Mail zugesendet.', 'reset' => 'Ihr Passwort wurde zurückgesetzt!', diff --git a/resources/lang/de/settings.php b/resources/lang/de/settings.php index 263c0f923..d8ffedbf2 100644 --- a/resources/lang/de/settings.php +++ b/resources/lang/de/settings.php @@ -195,6 +195,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'Hebräisch', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/de_informal/auth.php b/resources/lang/de_informal/auth.php index 4528eda40..918598533 100644 --- a/resources/lang/de_informal/auth.php +++ b/resources/lang/de_informal/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Passwort vergessen', 'reset_password_send_instructions' => 'Bitte gib Deine E-Mail-Adresse ein. Danach erhältst Du eine E-Mail mit einem Link zum Zurücksetzen Deines Passwortes.', 'reset_password_send_button' => 'Passwort zurücksetzen', - 'reset_password_sent_success' => 'Eine E-Mail mit dem Link zum Zurücksetzen Deines Passwortes wurde an :email gesendet.', + 'reset_password_sent' => 'Ein Link zum Zurücksetzen des Passworts wird an :email gesendet, wenn diese E-Mail-Adresse im System gefunden wird.', 'reset_password_success' => 'Dein Passwort wurde erfolgreich zurückgesetzt.', 'email_reset_subject' => 'Passwort zurücksetzen für :appName', 'email_reset_text' => 'Du erhältsts diese E-Mail, weil jemand versucht hat, Dein Passwort zurückzusetzen.', diff --git a/resources/lang/de_informal/common.php b/resources/lang/de_informal/common.php index 1fb2d6f78..c54b23afc 100644 --- a/resources/lang/de_informal/common.php +++ b/resources/lang/de_informal/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profilmenü', 'view_profile' => 'Profil ansehen', 'edit_profile' => 'Profil bearbeiten', + 'dark_mode' => 'Dunkler Modus', + 'light_mode' => 'Heller Modus', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/de_informal/passwords.php b/resources/lang/de_informal/passwords.php index 74149a7ed..3da092cb8 100644 --- a/resources/lang/de_informal/passwords.php +++ b/resources/lang/de_informal/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Passwörter müssen aus mindestens sechs Zeichen bestehen und mit der eingegebenen Wiederholung übereinstimmen.', 'user' => "Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.", - 'token' => 'Dieser Link zum Zurücksetzen des Passwortes ist ungültig!', + 'token' => 'Der Link zum Zurücksetzen Ihres Passworts ist entweder ungültig oder abgelaufen.', 'sent' => 'Der Link zum Zurücksetzen Ihres Passwortes wurde Ihnen per E-Mail zugesendet.', 'reset' => 'Ihr Passwort wurde zurückgesetzt!', diff --git a/resources/lang/de_informal/settings.php b/resources/lang/de_informal/settings.php index 9af19031d..a39e00e04 100644 --- a/resources/lang/de_informal/settings.php +++ b/resources/lang/de_informal/settings.php @@ -195,6 +195,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'Hebräisch', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/es/auth.php b/resources/lang/es/auth.php index 00ff8b137..25fc5b650 100644 --- a/resources/lang/es/auth.php +++ b/resources/lang/es/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Resetear Contraseña', 'reset_password_send_instructions' => 'Introduzca su correo electrónico a continuación y le será enviado un correo con un link para la restauración', 'reset_password_send_button' => 'Enviar Enlace de Reseteo', - 'reset_password_sent_success' => 'Un enlace para resetear la contraseña ha sido enviado a :email.', + 'reset_password_sent' => 'Un enlace para cambiar la contraseña será enviado a su dirección de correo electrónico si existe en nuestro sistema.', 'reset_password_success' => 'Su password ha sido reseteado de manera éxitosa.', 'email_reset_subject' => 'Resetee la contraseña de :appName', 'email_reset_text' => 'Está recibiendo este correo electrónico debido a que recibimos una solicitud de reseteo de contraseña de su cuenta.', diff --git a/resources/lang/es/common.php b/resources/lang/es/common.php index 45eff2d5f..b61b170b1 100644 --- a/resources/lang/es/common.php +++ b/resources/lang/es/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Menú de Perfil', 'view_profile' => 'Ver Perfil', 'edit_profile' => 'Editar Perfil', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Información', diff --git a/resources/lang/es/passwords.php b/resources/lang/es/passwords.php index 443f072c4..15e42d1ec 100644 --- a/resources/lang/es/passwords.php +++ b/resources/lang/es/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'La contraseña debe ser como mínimo de seis caracteres y coincidir con la confirmación.', 'user' => "No podemos encontrar un usuario con esta dirección de correo electrónico.", - 'token' => 'El token de reseteo de la contraseña es inválido.', + 'token' => 'El token de modificación de contraseña no es válido para esta dirección de correo electrónico.', 'sent' => '¡Hemos enviado a su cuenta de e-mail un enlace para restaurar su contraseña!', 'reset' => '¡Su contraseña ha sido restaurada!', diff --git a/resources/lang/es/settings.php b/resources/lang/es/settings.php index 57b91d033..7f249b04e 100644 --- a/resources/lang/es/settings.php +++ b/resources/lang/es/settings.php @@ -61,7 +61,7 @@ return [ 'reg_email_confirmation_toggle' => 'Requerir confirmación por Email', 'reg_confirm_email_desc' => 'Si se emplea la restricción por dominio, entonces se requerirá la confirmación por correo electrónico y esta opción será ignorada.', 'reg_confirm_restrict_domain' => 'Restricción de Dominio', - 'reg_confirm_restrict_domain_desc' => 'Introduzca una lista separada por comas de los dominio a los que les gustaría restringir el registro de usuarios. A los usuarios les será enviado un correo electrónico para confirmar la dirección antes de que se le permita interactuar con la aplicación.
    Tenga en cuenta que los usuarios podrán cambiar sus direcciones de correo electrónico después de registrarse exitosamente.', + 'reg_confirm_restrict_domain_desc' => 'Introduzca una lista separada por comas de los dominios para cuentas de correo a los que se les permitirá el registro de usuarios. A los usuarios les será enviado un correo electrónico para confirmar la dirección antes de que se le permita interactuar con la aplicación.
    Tenga en cuenta que los usuarios podrán cambiar sus direcciones de correo electrónico después de registrarse exitosamente.', 'reg_confirm_restrict_domain_placeholder' => 'Ninguna restricción establecida', // Maintenance settings @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/es_AR/auth.php b/resources/lang/es_AR/auth.php index aa54fa71f..834511041 100644 --- a/resources/lang/es_AR/auth.php +++ b/resources/lang/es_AR/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Restablecer la contraseña', 'reset_password_send_instructions' => 'Introduzca su correo electrónico a continuación y se le enviará un correo electrónico con un enlace para la restauración', 'reset_password_send_button' => 'Enviar enlace de restauración', - 'reset_password_sent_success' => 'Se envió un enlace para restablecer la contraseña a :email.', + 'reset_password_sent' => 'Un enlace para cambiar la contraseña será enviado a su dirección de correo electrónico si existe en nuestro sistema.', 'reset_password_success' => 'Su contraseña se restableció con éxito.', 'email_reset_subject' => 'Restauración de la contraseña de para la aplicación :appName', 'email_reset_text' => 'Ud. esta recibiendo este correo electrónico debido a que recibimos una solicitud de restauración de la contraseña de su cuenta.', diff --git a/resources/lang/es_AR/common.php b/resources/lang/es_AR/common.php index b7201101c..5f98271ac 100644 --- a/resources/lang/es_AR/common.php +++ b/resources/lang/es_AR/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Menu del Perfil', 'view_profile' => 'Ver Perfil', 'edit_profile' => 'Editar Perfil', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Información', diff --git a/resources/lang/es_AR/passwords.php b/resources/lang/es_AR/passwords.php index e38e55ed8..ab386c0d7 100644 --- a/resources/lang/es_AR/passwords.php +++ b/resources/lang/es_AR/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'La contraseña debe ser como mínimo de seis caracteres y coincidir con la confirmación.', 'user' => "No podemos encontrar un usuario con esta dirección de correo electrónico.", - 'token' => 'Este token de restablecimiento de contraseña no es válido.', + 'token' => 'El token de modificación de contraseña no es válido para esta dirección de correo electrónico.', 'sent' => '¡Hemos enviado a su cuenta de correo electrónico un enlace para restaurar su contraseña!', 'reset' => '¡Su contraseña fue restaurada!', diff --git a/resources/lang/es_AR/settings.php b/resources/lang/es_AR/settings.php index f218dd95c..9a27eedfd 100644 --- a/resources/lang/es_AR/settings.php +++ b/resources/lang/es_AR/settings.php @@ -193,6 +193,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/fa/auth.php b/resources/lang/fa/auth.php index 6961e049b..d64fce93a 100644 --- a/resources/lang/fa/auth.php +++ b/resources/lang/fa/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Reset Password', 'reset_password_send_instructions' => 'Enter your email below and you will be sent an email with a password reset link.', 'reset_password_send_button' => 'Send Reset Link', - 'reset_password_sent_success' => 'A password reset link has been sent to :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Your password has been successfully reset.', 'email_reset_subject' => 'Reset your :appName password', 'email_reset_text' => 'You are receiving this email because we received a password reset request for your account.', diff --git a/resources/lang/fa/common.php b/resources/lang/fa/common.php index c8b4a2b22..68c58b92b 100644 --- a/resources/lang/fa/common.php +++ b/resources/lang/fa/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profile Menu', 'view_profile' => 'View Profile', 'edit_profile' => 'Edit Profile', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/fa/passwords.php b/resources/lang/fa/passwords.php index f41ca7868..b408f3c2f 100644 --- a/resources/lang/fa/passwords.php +++ b/resources/lang/fa/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Passwords must be at least eight characters and match the confirmation.', 'user' => "We can't find a user with that e-mail address.", - 'token' => 'This password reset token is invalid.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'We have e-mailed your password reset link!', 'reset' => 'Your password has been reset!', diff --git a/resources/lang/fa/settings.php b/resources/lang/fa/settings.php index 35bb09cd4..f1345c743 100644 --- a/resources/lang/fa/settings.php +++ b/resources/lang/fa/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/fr/auth.php b/resources/lang/fr/auth.php index 99b41c070..07252420a 100644 --- a/resources/lang/fr/auth.php +++ b/resources/lang/fr/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Réinitialiser le mot de passe', 'reset_password_send_instructions' => 'Entrez votre adresse e-mail ci-dessous et un e-mail avec un lien de réinitialisation de mot de passe vous sera envoyé.', 'reset_password_send_button' => 'Envoyer un lien de réinitialisation', - 'reset_password_sent_success' => 'Un lien de réinitialisation a été envoyé à :email.', + 'reset_password_sent' => 'Un lien de réinitialisation du mot de passe sera envoyé à :email si cette adresse e-mail est trouvée dans le système.', 'reset_password_success' => 'Votre mot de passe a été réinitialisé avec succès.', 'email_reset_subject' => 'Réinitialisez votre mot de passe pour :appName', 'email_reset_text' => 'Vous recevez cet e-mail parce que nous avons reçu une demande de réinitialisation pour votre compte.', diff --git a/resources/lang/fr/common.php b/resources/lang/fr/common.php index 9a618d73a..4294c3d27 100644 --- a/resources/lang/fr/common.php +++ b/resources/lang/fr/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Menu du profil', 'view_profile' => 'Voir le profil', 'edit_profile' => 'Modifier le profil', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Informations', diff --git a/resources/lang/fr/passwords.php b/resources/lang/fr/passwords.php index 3852f5bf1..b0ff20e28 100644 --- a/resources/lang/fr/passwords.php +++ b/resources/lang/fr/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Les mots de passe doivent faire au moins 6 caractères et correspondre à la confirmation.', 'user' => "Nous n'avons pas trouvé d'utilisateur avec cette adresse.", - 'token' => 'Le jeton de réinitialisation est invalide.', + 'token' => 'Le mot de passe reset du token n\'est pas valide pour cette adresse e-mail.', 'sent' => 'Nous vous avons envoyé un lien de réinitialisation de mot de passe !', 'reset' => 'Votre mot de passe a été réinitialisé !', diff --git a/resources/lang/fr/settings.php b/resources/lang/fr/settings.php index ab56d8ea2..d2096ed75 100644 --- a/resources/lang/fr/settings.php +++ b/resources/lang/fr/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'Hébreu', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/he/auth.php b/resources/lang/he/auth.php index 8a982db01..733c84f9d 100644 --- a/resources/lang/he/auth.php +++ b/resources/lang/he/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'איפוס סיסמא', 'reset_password_send_instructions' => 'יש להזין את כתובת המייל למטה ואנו נשלח אלייך הוראות לאיפוס הסיסמא', 'reset_password_send_button' => 'שלח קישור לאיפוס סיסמא', - 'reset_password_sent_success' => 'שלחנו הוראות לאיפוס הסיסמא אל :email', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'סיסמתך עודכנה בהצלחה', 'email_reset_subject' => 'איפוס סיסמא ב :appName', 'email_reset_text' => 'קישור זה נשלח עקב בקשה לאיפוס סיסמא בחשבון שלך', diff --git a/resources/lang/he/common.php b/resources/lang/he/common.php index 55c50bfb9..0dc1cc43d 100644 --- a/resources/lang/he/common.php +++ b/resources/lang/he/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profile Menu', 'view_profile' => 'הצג פרופיל', 'edit_profile' => 'ערוך פרופיל', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'מידע', diff --git a/resources/lang/he/passwords.php b/resources/lang/he/passwords.php index 9ada7bcbf..17fad68d5 100644 --- a/resources/lang/he/passwords.php +++ b/resources/lang/he/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'הסיסמא חייבת להיות בעלת 6 תווים ולהתאים לאימות', 'user' => "לא ניתן למצוא משתמש עם המייל שסופק", - 'token' => 'איפוס הסיסמא אינו תקין', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'נשלח אליך אי-מייל עם קישור לאיפוס הסיסמא', 'reset' => 'איפוס הסיסמא הושלם בהצלחה!', diff --git a/resources/lang/he/settings.php b/resources/lang/he/settings.php index 103f9398d..e3cd0ead5 100755 --- a/resources/lang/he/settings.php +++ b/resources/lang/he/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/hu/auth.php b/resources/lang/hu/auth.php index dce23545e..a13c8300e 100644 --- a/resources/lang/hu/auth.php +++ b/resources/lang/hu/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Jelszó visszaállítása', 'reset_password_send_instructions' => 'Meg kell adni az email címet amire egy jelszó visszaállító hivatkozás lesz elküldve.', 'reset_password_send_button' => 'Visszaállító hivatkozás elküldése', - 'reset_password_sent_success' => 'Jelszó visszaállító hivatkozás elküldve :email címre.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'A jelszó sikeresen visszaállítva.', 'email_reset_subject' => ':appName jelszó visszaállítása', 'email_reset_text' => 'Ezt az emailt azért küldtük mert egy jelszó visszaállításra vonatkozó kérést kaptunk ebből a fiókból.', diff --git a/resources/lang/hu/common.php b/resources/lang/hu/common.php index 72bc3324b..3abd3bf27 100644 --- a/resources/lang/hu/common.php +++ b/resources/lang/hu/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profil menü', 'view_profile' => 'Profil megtekintése', 'edit_profile' => 'Profil szerkesztése', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Információ', diff --git a/resources/lang/hu/passwords.php b/resources/lang/hu/passwords.php index bacc08b08..e06c6f6e3 100644 --- a/resources/lang/hu/passwords.php +++ b/resources/lang/hu/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'A jelszónak legalább hat karakterből kell állnia és egyeznie kell a megerősítéssel.', 'user' => "Nem található felhasználó ezzel az e-mail címmel.", - 'token' => 'Ez a jelszó visszaállító vezérjel érvénytelen.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'E-mailben elküldtük a jelszó visszaállító hivatkozást!', 'reset' => 'A jelszó visszaállítva!', diff --git a/resources/lang/hu/settings.php b/resources/lang/hu/settings.php index 8a87db85a..f0c59da4b 100644 --- a/resources/lang/hu/settings.php +++ b/resources/lang/hu/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/it/auth.php b/resources/lang/it/auth.php index 234af2eeb..8e8ff8f07 100755 --- a/resources/lang/it/auth.php +++ b/resources/lang/it/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Reimposta Password', 'reset_password_send_instructions' => 'Inserisci il tuo indirizzo sotto e ti verrà inviata una mail contenente un link per resettare la tua password.', 'reset_password_send_button' => 'Invia Link Reset', - 'reset_password_sent_success' => 'Un link di reset è stato mandato a :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'La tua password è stata resettata correttamente.', 'email_reset_subject' => 'Reimposta la password di :appName', 'email_reset_text' => 'Stai ricevendo questa mail perché abbiamo ricevuto una richiesta di reset della password per il tuo account.', diff --git a/resources/lang/it/common.php b/resources/lang/it/common.php index d8dbce451..73b4cad54 100755 --- a/resources/lang/it/common.php +++ b/resources/lang/it/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Menu del profilo', 'view_profile' => 'Visualizza Profilo', 'edit_profile' => 'Modifica Profilo', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/it/passwords.php b/resources/lang/it/passwords.php index 0f95a3e06..604e02fe2 100755 --- a/resources/lang/it/passwords.php +++ b/resources/lang/it/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'La password deve avere almeno sei caratteri e corrispondere alla conferma.', 'user' => "Non possiamo trovare un utente per quella mail.", - 'token' => 'Questo token per reimpostare la password non è valido.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'Ti abbiamo inviato via mail il link per reimpostare la password!', 'reset' => 'La tua password è stata resettata!', diff --git a/resources/lang/it/settings.php b/resources/lang/it/settings.php index d4fb0b9c6..34342d3c7 100755 --- a/resources/lang/it/settings.php +++ b/resources/lang/it/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/ja/auth.php b/resources/lang/ja/auth.php index d0db7d080..a700ffb95 100644 --- a/resources/lang/ja/auth.php +++ b/resources/lang/ja/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'パスワードリセット', 'reset_password_send_instructions' => '以下にEメールアドレスを入力すると、パスワードリセットリンクが記載されたメールが送信されます。', 'reset_password_send_button' => 'リセットリンクを送信', - 'reset_password_sent_success' => ':emailへリセットリンクを送信しました。', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'パスワードがリセットされました。', 'email_reset_subject' => ':appNameのパスワードをリセット', 'email_reset_text' => 'このメールは、パスワードリセットがリクエストされたため送信されています。', diff --git a/resources/lang/ja/common.php b/resources/lang/ja/common.php index 2a142e55f..9611e232b 100644 --- a/resources/lang/ja/common.php +++ b/resources/lang/ja/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profile Menu', 'view_profile' => 'プロフィール表示', 'edit_profile' => 'プロフィール編集', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/ja/passwords.php b/resources/lang/ja/passwords.php index 3531c73c7..e92a35500 100644 --- a/resources/lang/ja/passwords.php +++ b/resources/lang/ja/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'パスワードは6文字以上である必要があります。', 'user' => "このEメールアドレスに一致するユーザが見つかりませんでした。", - 'token' => 'このパスワードリセットトークンは無効です。', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'パスワードリセットリンクを送信しました。', 'reset' => 'パスワードはリセットされました。', diff --git a/resources/lang/ja/settings.php b/resources/lang/ja/settings.php index 3da916877..c7a9773e3 100644 --- a/resources/lang/ja/settings.php +++ b/resources/lang/ja/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/ko/auth.php b/resources/lang/ko/auth.php index 5346c5540..9c4d98bcb 100644 --- a/resources/lang/ko/auth.php +++ b/resources/lang/ko/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => '비밀번호 바꾸기', 'reset_password_send_instructions' => '메일 주소를 입력하세요. 이 주소로 해당 과정을 위한 링크를 보낼 것입니다.', 'reset_password_send_button' => '메일 보내기', - 'reset_password_sent_success' => ':email로 메일을 보냈습니다.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => '비밀번호를 바꿨습니다.', 'email_reset_subject' => ':appName 비밀번호 바꾸기', 'email_reset_text' => '비밀번호를 바꿉니다.', diff --git a/resources/lang/ko/common.php b/resources/lang/ko/common.php index c2b09080c..56fc323f9 100644 --- a/resources/lang/ko/common.php +++ b/resources/lang/ko/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => '프로필', 'view_profile' => '프로필 보기', 'edit_profile' => '프로필 바꾸기', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => '정보', diff --git a/resources/lang/ko/passwords.php b/resources/lang/ko/passwords.php index 35a2a5933..016339771 100644 --- a/resources/lang/ko/passwords.php +++ b/resources/lang/ko/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => '여덟 글자를 넘어야 합니다.', 'user' => "메일 주소를 가진 사용자가 없습니다.", - 'token' => '이 링크는 더 이상 유효하지 않습니다.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => '메일을 보냈습니다.', 'reset' => '비밀번호를 바꿨습니다.', diff --git a/resources/lang/ko/settings.php b/resources/lang/ko/settings.php index bd23e380f..4bf653f6c 100755 --- a/resources/lang/ko/settings.php +++ b/resources/lang/ko/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/nl/auth.php b/resources/lang/nl/auth.php index c691bf6b5..03211e1b9 100644 --- a/resources/lang/nl/auth.php +++ b/resources/lang/nl/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Wachtwoord Herstellen', 'reset_password_send_instructions' => 'Geef je e-mail en we sturen je een link om je wachtwoord te herstellen', 'reset_password_send_button' => 'Link Sturen', - 'reset_password_sent_success' => 'Een link om je wachtwoord te herstellen is verstuurd naar :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Je wachtwoord is succesvol hersteld.', 'email_reset_subject' => 'Herstel je wachtwoord van :appName', 'email_reset_text' => 'Je ontvangt deze e-mail zodat je je wachtwoord kunt herstellen.', diff --git a/resources/lang/nl/common.php b/resources/lang/nl/common.php index 01e9969ef..2351ab2db 100644 --- a/resources/lang/nl/common.php +++ b/resources/lang/nl/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profiel menu', 'view_profile' => 'Profiel Weergeven', 'edit_profile' => 'Profiel Bewerken', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/nl/passwords.php b/resources/lang/nl/passwords.php index a1efd480e..e0f36816c 100644 --- a/resources/lang/nl/passwords.php +++ b/resources/lang/nl/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Wachtwoorden moeten overeenkomen en minimaal zes tekens lang zijn.', 'user' => "We kunnen niemand vinden met dat e-mailadres.", - 'token' => 'De token om het wachtwoord te herstellen is ongeldig.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'We hebben je een link gestuurd om je wachtwoord te herstellen!', 'reset' => 'Je wachtwoord is hersteld!', diff --git a/resources/lang/nl/settings.php b/resources/lang/nl/settings.php index 069ee65f8..cdd1b6fef 100644 --- a/resources/lang/nl/settings.php +++ b/resources/lang/nl/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/pl/auth.php b/resources/lang/pl/auth.php index a85159a1b..bb46cb2de 100644 --- a/resources/lang/pl/auth.php +++ b/resources/lang/pl/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Resetowanie hasła', 'reset_password_send_instructions' => 'Wprowadź adres e-mail powiązany z Twoim kontem, by otrzymać link do resetowania hasła.', 'reset_password_send_button' => 'Wyślij link do resetowania hasła', - 'reset_password_sent_success' => 'Wysłano link do resetowania hasła na adres :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Hasło zostało zresetowane pomyślnie.', 'email_reset_subject' => 'Resetowanie hasła do :appName', 'email_reset_text' => 'Otrzymujesz tę wiadomość ponieważ ktoś zażądał zresetowania hasła do Twojego konta.', diff --git a/resources/lang/pl/common.php b/resources/lang/pl/common.php index f91a682e5..9fe313858 100644 --- a/resources/lang/pl/common.php +++ b/resources/lang/pl/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Menu profilu', 'view_profile' => 'Zobacz profil', 'edit_profile' => 'Edytuj profil', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Informacje', diff --git a/resources/lang/pl/passwords.php b/resources/lang/pl/passwords.php index 8c9eae227..02f920127 100644 --- a/resources/lang/pl/passwords.php +++ b/resources/lang/pl/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Hasło musi zawierać co najmniej 6 znaków i być zgodne z powtórzeniem.', 'user' => "Nie znaleziono użytkownika o takim adresie e-mail.", - 'token' => 'Ten token resetowania hasła jest nieprawidłowy.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'Wysłaliśmy Ci link do resetowania hasła!', 'reset' => 'Twoje hasło zostało zresetowane!', diff --git a/resources/lang/pl/settings.php b/resources/lang/pl/settings.php index 97f4222d6..eefe2b19e 100644 --- a/resources/lang/pl/settings.php +++ b/resources/lang/pl/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/pt/auth.php b/resources/lang/pt/auth.php index 6961e049b..d64fce93a 100644 --- a/resources/lang/pt/auth.php +++ b/resources/lang/pt/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Reset Password', 'reset_password_send_instructions' => 'Enter your email below and you will be sent an email with a password reset link.', 'reset_password_send_button' => 'Send Reset Link', - 'reset_password_sent_success' => 'A password reset link has been sent to :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Your password has been successfully reset.', 'email_reset_subject' => 'Reset your :appName password', 'email_reset_text' => 'You are receiving this email because we received a password reset request for your account.', diff --git a/resources/lang/pt/common.php b/resources/lang/pt/common.php index c8b4a2b22..68c58b92b 100644 --- a/resources/lang/pt/common.php +++ b/resources/lang/pt/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profile Menu', 'view_profile' => 'View Profile', 'edit_profile' => 'Edit Profile', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/pt/passwords.php b/resources/lang/pt/passwords.php index f41ca7868..b408f3c2f 100644 --- a/resources/lang/pt/passwords.php +++ b/resources/lang/pt/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Passwords must be at least eight characters and match the confirmation.', 'user' => "We can't find a user with that e-mail address.", - 'token' => 'This password reset token is invalid.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'We have e-mailed your password reset link!', 'reset' => 'Your password has been reset!', diff --git a/resources/lang/pt/settings.php b/resources/lang/pt/settings.php index 35bb09cd4..f1345c743 100644 --- a/resources/lang/pt/settings.php +++ b/resources/lang/pt/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/pt_BR/auth.php b/resources/lang/pt_BR/auth.php index fd0cf823d..094cdf4d2 100644 --- a/resources/lang/pt_BR/auth.php +++ b/resources/lang/pt_BR/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Redefinir Senha', 'reset_password_send_instructions' => 'Insira seu e-mail abaixo e uma mensagem com o link de redefinição de senha lhe será enviada.', 'reset_password_send_button' => 'Enviar o Link de Redefinição', - 'reset_password_sent_success' => 'Um link de redefinição de senha foi enviado para :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Sua senha foi redefinida com sucesso.', 'email_reset_subject' => 'Redefina a senha de :appName', 'email_reset_text' => 'Você recebeu esse e-mail pois recebemos uma solicitação de redefinição de senha para a sua conta.', diff --git a/resources/lang/pt_BR/common.php b/resources/lang/pt_BR/common.php index f32774014..e57467ec1 100644 --- a/resources/lang/pt_BR/common.php +++ b/resources/lang/pt_BR/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Menu de Perfil', 'view_profile' => 'Visualizar Perfil', 'edit_profile' => 'Editar Perfil', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Informações', diff --git a/resources/lang/pt_BR/passwords.php b/resources/lang/pt_BR/passwords.php index 0d452c361..07865c43d 100644 --- a/resources/lang/pt_BR/passwords.php +++ b/resources/lang/pt_BR/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Senhas devem ter ao menos oito caracteres e ser iguais à confirmação.', 'user' => "Não pudemos encontrar um usuário com o e-mail fornecido.", - 'token' => 'O token de redefinição de senha é inválido.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'Enviamos o link de redefinição de senha para o seu e-mail!', 'reset' => 'Sua senha foi redefinida com sucesso!', diff --git a/resources/lang/pt_BR/settings.php b/resources/lang/pt_BR/settings.php index bc78f8328..7176eb9f3 100644 --- a/resources/lang/pt_BR/settings.php +++ b/resources/lang/pt_BR/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/ru/auth.php b/resources/lang/ru/auth.php index 369da7aa3..1f0ec6b80 100644 --- a/resources/lang/ru/auth.php +++ b/resources/lang/ru/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Сброс пароля', 'reset_password_send_instructions' => 'Введите свой адрес электронной почты ниже, и вам будет отправлено письмо со ссылкой для сброса пароля.', 'reset_password_send_button' => 'Сбросить пароль', - 'reset_password_sent_success' => 'Ссылка для сброса пароля была отправлена на :email.', + 'reset_password_sent' => 'Ссылка для сброса пароля будет выслана на :email, если этот адрес находится в системе.', 'reset_password_success' => 'Ваш пароль был успешно сброшен.', 'email_reset_subject' => 'Сброс пароля от :appName', 'email_reset_text' => 'Вы получили это письмо, потому что запросили сброс пароля для вашей учетной записи.', diff --git a/resources/lang/ru/common.php b/resources/lang/ru/common.php index 50bd672e7..12fac6507 100644 --- a/resources/lang/ru/common.php +++ b/resources/lang/ru/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Меню профиля', 'view_profile' => 'Посмотреть профиль', 'edit_profile' => 'Редактировать профиль', + 'dark_mode' => 'Темный режим', + 'light_mode' => 'Светлый режим', // Layout tabs 'tab_info' => 'Информация', diff --git a/resources/lang/ru/passwords.php b/resources/lang/ru/passwords.php index d04970f08..433c70454 100644 --- a/resources/lang/ru/passwords.php +++ b/resources/lang/ru/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Пароль должен содержать не менее восьми символов и совпадать с подтверждением.', 'user' => "Пользователя с данным адресом электронной почты не существует.", - 'token' => 'Токен сброса пароля недействителен.', + 'token' => 'Токен сброса пароля недействителен для этого адреса электронной почты.', 'sent' => 'Ссылка для сброса пароля отправлена на вашу почту!', 'reset' => 'Ваш пароль был сброшен!', diff --git a/resources/lang/ru/settings.php b/resources/lang/ru/settings.php index 8eeb3bca1..0981aaa73 100755 --- a/resources/lang/ru/settings.php +++ b/resources/lang/ru/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/sk/auth.php b/resources/lang/sk/auth.php index fcce42bbd..2b2e83a17 100644 --- a/resources/lang/sk/auth.php +++ b/resources/lang/sk/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Reset hesla', 'reset_password_send_instructions' => 'Zadajte svoj email nižšie a bude Vám odoslaný email s odkazom pre reset hesla.', 'reset_password_send_button' => 'Poslať odkaz na reset hesla', - 'reset_password_sent_success' => 'Odkaz na reset hesla bol poslaný na :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Vaše heslo bolo úspešne resetované.', 'email_reset_subject' => 'Reset Vášho :appName hesla', 'email_reset_text' => 'Tento email Ste dostali pretože sme dostali požiadavku na reset hesla pre Váš účet.', diff --git a/resources/lang/sk/common.php b/resources/lang/sk/common.php index 30faa9e77..5674fd5a7 100644 --- a/resources/lang/sk/common.php +++ b/resources/lang/sk/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profile Menu', 'view_profile' => 'Zobraziť profil', 'edit_profile' => 'Upraviť profil', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/sk/passwords.php b/resources/lang/sk/passwords.php index de7d24442..30ed1b782 100644 --- a/resources/lang/sk/passwords.php +++ b/resources/lang/sk/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Heslo musí obsahovať aspoň šesť znakov a musí byť rovnaké ako potvrdzujúce.', 'user' => "Nenašli sme používateľa s takou emailovou adresou.", - 'token' => 'Tento token pre reset hesla je neplatný.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'Poslali sme Vám email s odkazom na reset hesla!', 'reset' => 'Vaše heslo bolo resetované!', diff --git a/resources/lang/sk/settings.php b/resources/lang/sk/settings.php index ce6821890..75a847b0a 100644 --- a/resources/lang/sk/settings.php +++ b/resources/lang/sk/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/sl/auth.php b/resources/lang/sl/auth.php index 171baa328..32aa9596e 100644 --- a/resources/lang/sl/auth.php +++ b/resources/lang/sl/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Ponastavi geslo', 'reset_password_send_instructions' => 'Spodaj vpišite vaš e-poštni naslov in prejeli boste e-pošto s povezavo za ponastavitev gesla.', 'reset_password_send_button' => 'Pošlji povezavo za ponastavitev', - 'reset_password_sent_success' => 'Povezava za ponastavitev gesla je bila poslana na :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Vaše geslo je bilo uspešno spremenjeno.', 'email_reset_subject' => 'Ponastavi svoje :appName geslo', 'email_reset_text' => 'To e-poštno sporočilo ste prejeli, ker smo prejeli zahtevo za ponastavitev gesla za vaš račun.', diff --git a/resources/lang/sl/common.php b/resources/lang/sl/common.php index 6508509ea..9c1480d05 100644 --- a/resources/lang/sl/common.php +++ b/resources/lang/sl/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Meni profila', 'view_profile' => 'Ogled profila', 'edit_profile' => 'Uredi profil', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Informacije', diff --git a/resources/lang/sl/passwords.php b/resources/lang/sl/passwords.php index 12e52ef28..774cf4cbf 100644 --- a/resources/lang/sl/passwords.php +++ b/resources/lang/sl/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Gesla morajo biti najmanj osem znakov in se morajo ujemati s potrditvijo.', 'user' => "Ne moremo najti uporabnika s tem e-poštnim naslovom.", - 'token' => 'Žeton za ponastavitev gesla ni veljaven.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'Poslali smo vam povezavo za ponastavitev gesla!', 'reset' => 'Vaše geslo je bilo ponastavljeno!', diff --git a/resources/lang/sl/settings.php b/resources/lang/sl/settings.php index 09e687c8c..24cd9229a 100644 --- a/resources/lang/sl/settings.php +++ b/resources/lang/sl/settings.php @@ -196,6 +196,7 @@ V tej vlogi trenutno ni dodeljen noben uporabnik', 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/sv/auth.php b/resources/lang/sv/auth.php index 0ca269e2e..155e4b002 100644 --- a/resources/lang/sv/auth.php +++ b/resources/lang/sv/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Återställ lösenord', 'reset_password_send_instructions' => 'Ange din e-postadress nedan så skickar vi ett mail med en länk för att återställa ditt lösenord.', 'reset_password_send_button' => 'Skicka återställningslänk', - 'reset_password_sent_success' => 'En länk för att återställa lösenordet har skickats till :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Ditt lösenord har återställts.', 'email_reset_subject' => 'Återställ ditt lösenord till :appName', 'email_reset_text' => 'Du får detta mail eftersom vi fått en begäran om att återställa lösenordet till ditt konto.', diff --git a/resources/lang/sv/common.php b/resources/lang/sv/common.php index 1c37af277..9b91e2b5a 100644 --- a/resources/lang/sv/common.php +++ b/resources/lang/sv/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profilmeny', 'view_profile' => 'Visa profil', 'edit_profile' => 'Redigera profil', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Information', diff --git a/resources/lang/sv/passwords.php b/resources/lang/sv/passwords.php index 8924edc7a..9f5545f36 100644 --- a/resources/lang/sv/passwords.php +++ b/resources/lang/sv/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Lösenord måste vara minst sex tecken långa och anges likadant två gånger.', 'user' => "Det finns ingen användare med den e-postadressen.", - 'token' => 'Återställningskoden är ogiltig.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'Vi har mailat dig en länk för att återställa ditt lösenord!', 'reset' => 'Ditt lösenord har blivit återställt!', diff --git a/resources/lang/sv/settings.php b/resources/lang/sv/settings.php index 05284cc5a..488f52cc3 100644 --- a/resources/lang/sv/settings.php +++ b/resources/lang/sv/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/tr/activities.php b/resources/lang/tr/activities.php index ccc55e172..cb8101461 100644 --- a/resources/lang/tr/activities.php +++ b/resources/lang/tr/activities.php @@ -6,41 +6,41 @@ return [ // Pages - 'page_create' => 'saya oluşturuldu', + 'page_create' => 'sayfa oluşturdu', 'page_create_notification' => 'Sayfa Başarıyla Oluşturuldu', - 'page_update' => 'sayfa güncellendi', + 'page_update' => 'sayfayı güncelledi', 'page_update_notification' => 'Sayfa Başarıyla Güncellendi', - 'page_delete' => 'sayfa silindi', + 'page_delete' => 'sayfayı sildi', 'page_delete_notification' => 'Sayfa Başarıyla Silindi', - 'page_restore' => 'sayfa kurtarıldı', - 'page_restore_notification' => 'Sayfa Başarıyla Kurtarıldı', - 'page_move' => 'sayfa taşındı', + 'page_restore' => 'sayfayı eski haline getirdi', + 'page_restore_notification' => 'Sayfa Başarıyla Eski Haline Getirildi', + 'page_move' => 'sayfayı taşıdı', // Chapters - 'chapter_create' => 'bölüm oluşturuldu', + 'chapter_create' => 'bölüm oluşturdu', 'chapter_create_notification' => 'Bölüm Başarıyla Oluşturuldu', - 'chapter_update' => 'bölüm güncellendi', + 'chapter_update' => 'bölümü güncelledi', 'chapter_update_notification' => 'Bölüm Başarıyla Güncellendi', - 'chapter_delete' => 'bölüm silindi', + 'chapter_delete' => 'bölümü sildi', 'chapter_delete_notification' => 'Bölüm Başarıyla Silindi', - 'chapter_move' => 'bölüm taşındı', + 'chapter_move' => 'bölümü taşıdı', // Books - 'book_create' => 'kitap oluşturuldu', + 'book_create' => 'kitap oluşturdu', 'book_create_notification' => 'Kitap Başarıyla Oluşturuldu', - 'book_update' => 'kitap güncellendi', + 'book_update' => 'kitabı güncelledi', 'book_update_notification' => 'Kitap Başarıyla Güncellendi', - 'book_delete' => 'kitap silindi', + 'book_delete' => 'kitabı sildi', 'book_delete_notification' => 'Kitap Başarıyla Silindi', - 'book_sort' => 'kitap düzenlendi', + 'book_sort' => 'kitabı sıraladı', 'book_sort_notification' => 'Kitap Başarıyla Yeniden Sıralandı', // Bookshelves - 'bookshelf_create' => 'kitaplık oluşturuldu', + 'bookshelf_create' => 'kitaplık oluşturdu', 'bookshelf_create_notification' => 'Kitaplık Başarıyla Oluşturuldu', - 'bookshelf_update' => 'kitaplık güncellendi', + 'bookshelf_update' => 'kitaplığı güncelledi', 'bookshelf_update_notification' => 'Kitaplık Başarıyla Güncellendi', - 'bookshelf_delete' => 'kitaplık silindi', + 'bookshelf_delete' => 'kitaplığı sildi', 'bookshelf_delete_notification' => 'Kitaplık Başarıyla Silindi', // Other diff --git a/resources/lang/tr/auth.php b/resources/lang/tr/auth.php index 2999f7cae..6a0e2c1b5 100644 --- a/resources/lang/tr/auth.php +++ b/resources/lang/tr/auth.php @@ -6,72 +6,72 @@ */ return [ - 'failed' => 'Girilen bilgiler bizdeki kayıtlarla uyuşmuyor.', + 'failed' => 'Girdiğiniz bilgiler kayıtlarımızla uyuşmuyor.', 'throttle' => 'Çok fazla giriş yapmaya çalıştınız. Lütfen :seconds saniye içinde tekrar deneyin.', // Login & Register - 'sign_up' => 'Kayıt Ol', + 'sign_up' => 'Kaydol', 'log_in' => 'Giriş Yap', 'log_in_with' => ':socialDriver ile giriş yap', - 'sign_up_with' => ':socialDriver ile kayıt ol', + 'sign_up_with' => ':socialDriver ile kaydol', 'logout' => 'Çıkış Yap', 'name' => 'İsim', 'username' => 'Kullanıcı Adı', - 'email' => 'E-Posta', + 'email' => 'E-posta', 'password' => 'Şifre', - 'password_confirm' => 'Şifreyi onayla', - 'password_hint' => 'En az 5 karakter olmalı', + 'password_confirm' => 'Şifreyi Onaylayın', + 'password_hint' => 'En az 8 karakter olmalı', 'forgot_password' => 'Şifrenizi mi unuttunuz?', 'remember_me' => 'Beni Hatırla', - 'ldap_email_hint' => 'Hesabı kullanmak istediğiniz e-mail adresinizi giriniz.', + 'ldap_email_hint' => 'Bu hesap için kullanmak istediğiniz e-posta adresini giriniz.', 'create_account' => 'Hesap Oluştur', 'already_have_account' => 'Zaten bir hesabınız var mı?', 'dont_have_account' => 'Hesabınız yok mu?', - 'social_login' => 'Diğer Servisler ile Giriş Yap', - 'social_registration' => 'Diğer Servisler ile Kayıt Ol', - 'social_registration_text' => 'Diğer servisler ile kayıt ol ve giriş yap.', + 'social_login' => 'Diğer Servisler ile Giriş Yapın', + 'social_registration' => 'Diğer Servisler ile Kaydolun', + 'social_registration_text' => 'Başka bir servis aracılığıyla kaydolun ve giriş yapın.', - 'register_thanks' => 'Kayıt olduğunuz için teşekkürler!', - 'register_confirm' => 'Lütfen e-posta adresinizi kontrol edin ve gelen doğrulama bağlantısına tıklayınız. :appName.', - 'registrations_disabled' => 'Kayıt olma özelliği geçici olarak kısıtlanmıştır', - 'registration_email_domain_invalid' => 'Bu e-mail sağlayıcısının bu uygulamaya erişim izni yoktur.', - 'register_success' => 'Artık kayıtlı bir kullanıcı olarak giriş yaptınız.', + 'register_thanks' => 'Kaydolduğunuz için teşekkürler!', + 'register_confirm' => ':appName erişimi için lütfen e-posta adresinizi kontrol edin ve size gönderilen doğrulama bağlantısına tıklayın.', + 'registrations_disabled' => 'Kayıtlar devre dışı bırakılmıştır', + 'registration_email_domain_invalid' => 'Bu e-posta sağlayıcısının uygulamaya erişim izni bulunmuyor', + 'register_success' => 'Kaydolduğunuz için teşekkürler! Artık kayıtlı bir kullanıcı olarak giriş yaptınız.', // Password Reset - 'reset_password' => 'Parolayı Sıfırla', - 'reset_password_send_instructions' => 'Aşağıya e-mail adresinizi girdiğinizde parola yenileme bağlantısı mail adresinize gönderilecektir.', - 'reset_password_send_button' => '>Sıfırlama Bağlantısını Gönder', - 'reset_password_sent_success' => 'Sıfırlama bağlantısı :email adresinize gönderildi.', - 'reset_password_success' => 'Parolanız başarıyla sıfırlandı.', - 'email_reset_subject' => ':appName şifrenizi sıfırlayın.', - 'email_reset_text' => ' Parola sıfırlama isteğinde bulunduğunuz için bu maili görüntülüyorsunuz.', - 'email_reset_not_requested' => 'Eğer bu parola sıfırlama isteğinde bulunmadıysanız herhangi bir işlem yapmanıza gerek yoktur.', + 'reset_password' => 'Şifreyi Sıfırla', + 'reset_password_send_instructions' => 'Aşağıya gireceğiniz e-posta adresine şifre sıfırlama bağlantısı gönderilecektir.', + 'reset_password_send_button' => 'Sıfırlama Bağlantısını Gönder', + 'reset_password_sent' => 'Şifre sıfırlama bağlantısı, :email adresinin sistemde bulunması durumunda e-posta olarak gönderilecektir.', + 'reset_password_success' => 'Şifreniz başarıyla sıfırlandı.', + 'email_reset_subject' => ':appName şifrenizi sıfırlayın', + 'email_reset_text' => 'Hesap şifrenizi sıfırlama isteğinde bulunduğunuz için bu e-postayı aldınız.', + 'email_reset_not_requested' => 'Şifre sıfırlama isteğinde bulunmadıysanız herhangi bir işlem yapmanıza gerek yoktur.', // Email Confirmation - 'email_confirm_subject' => ':appName için girdiğiniz mail adresiniz onaylayınız', - 'email_confirm_greeting' => ':appName\'e katıldığınız için teşekkürler!', - 'email_confirm_text' => 'Lütfen e-mail adresinizi aşağıda bulunan butona tıklayarak onaylayınız:', - 'email_confirm_action' => 'E-Maili Onayla', - 'email_confirm_send_error' => 'e-mail onayı gerekli fakat sistem mail göndermeyi başaramadı. Yöneticiniz ile görüşüp kurulumlarda bir sorun olmadığını doğrulayın.', - 'email_confirm_success' => 'e-mail adresiniz onaylandı!', - 'email_confirm_resent' => 'Doğrulama maili gönderildi, lütfen gelen kutunuzu kontrol ediniz...', + 'email_confirm_subject' => ':appName için girdiğiniz e-posta adresini doğrulayın', + 'email_confirm_greeting' => ':appName uygulamasına katıldığınız için teşekkürler!', + 'email_confirm_text' => 'Lütfen aşağıdaki butona tıklayarak e-posta adresinizi doğrulayın:', + 'email_confirm_action' => 'E-posta Adresini Doğrula', + 'email_confirm_send_error' => 'E-posta adresinin doğrulanması gerekiyor fakat sistem, doğrulama bağlantısını göndermeyi başaramadı. E-posta adresinin doğru bir şekilde ayarlığından emin olmak için yöneticiyle iletişime geçin.', + 'email_confirm_success' => 'E-posta adresiniz doğrulandı!', + 'email_confirm_resent' => 'Doğrulama e-postası tekrar gönderildi, lütfen gelen kutunuzu kontrol ediniz.', - 'email_not_confirmed' => 'E-mail Adresi Doğrulanmadı', - 'email_not_confirmed_text' => 'Sağlamış olduğunuz e-mail adresi henüz doğrulanmadı.', - 'email_not_confirmed_click_link' => 'Lütfen kayıt olduktan kısa süre sonra size gönderilen maildeki bağlantıya tıklayın ve mail adresinizi onaylayın.', - 'email_not_confirmed_resend' => 'Eğer gelen maili bulamadıysanız aşağıdaki formu tekrar doldurarak onay mailini kendinize tekrar gönderebilirsiniz.', - 'email_not_confirmed_resend_button' => 'Doğrulama Mailini Yeniden Yolla', + 'email_not_confirmed' => 'E-posta Adresi Doğrulanmadı', + 'email_not_confirmed_text' => 'E-posta adresiniz henüz doğrulanmadı.', + 'email_not_confirmed_click_link' => 'Lütfen kaydolduktan hemen sonra size gönderilen e-postadaki bağlantıya tıklayın.', + 'email_not_confirmed_resend' => 'Eğer e-postayı bulamıyorsanız, aşağıdaki formu doldurarak doğrulama e-postasının tekrar gönderilmesini sağlayabilirsiniz.', + 'email_not_confirmed_resend_button' => 'Doğrulama E-postasını Tekrar Gönder', // User Invite - 'user_invite_email_subject' => ':appName\'e katılma daveti aldınız!', - 'user_invite_email_greeting' => 'Sizin için :appName üzerinde bir hesap oluşturuldu.', - 'user_invite_email_text' => 'Parola belirlemek ve erişebilmek için aşağıdaki butona tıklayın:', + 'user_invite_email_subject' => ':appName uygulamasına davet edildiniz!', + 'user_invite_email_greeting' => ':appName üzerinde sizin için bir hesap oluşturuldu.', + 'user_invite_email_text' => 'Hesap şifrenizi belirlemek ve hesabınıza erişim sağlayabilmek için aşağıdaki butona tıklayın:', 'user_invite_email_action' => 'Hesap Şifresini Belirleyin', - 'user_invite_page_welcome' => ':appName\'e hoş geldiniz!', - 'user_invite_page_text' => 'Hesap açılışını tamamlamak ve erişim izni alabilmek için daha sonraki girişlerinizde kullanabilmek üzere bir şifre belirlemeniz gerekiyor.', - 'user_invite_page_confirm_button' => 'Parolayı Onayla', - 'user_invite_success' => 'Parolanız belirlendi, artık :appName\'e erişebilirsiniz!' + 'user_invite_page_welcome' => ':appName uygulamasına hoş geldiniz!', + 'user_invite_page_text' => 'Hesap kurulumunuzu tamamlamak ve gelecekteki :appName ziyaretlerinizde hesabınıza erişim sağlayabilmeniz için bir şifre belirlemeniz gerekiyor.', + 'user_invite_page_confirm_button' => 'Şifreyi Onayla', + 'user_invite_success' => 'Şifreniz ayarlandı, artık :appName uygulamasına giriş yapabilirsiniz!' ]; \ No newline at end of file diff --git a/resources/lang/tr/common.php b/resources/lang/tr/common.php index 740757671..ae9bfe847 100644 --- a/resources/lang/tr/common.php +++ b/resources/lang/tr/common.php @@ -11,7 +11,7 @@ return [ 'save' => 'Kaydet', 'continue' => 'Devam', 'select' => 'Seç', - 'toggle_all' => 'Hepsini Değiştir', + 'toggle_all' => 'Hepsini Aç/Kapat', 'more' => 'Daha Fazla', // Form Labels @@ -19,12 +19,12 @@ return [ 'description' => 'Açıklama', 'role' => 'Rol', 'cover_image' => 'Kapak resmi', - 'cover_image_description' => 'Bu resim yaklaşık 440x250px boyutlarında olmalıdır.', + 'cover_image_description' => 'Bu görsel yaklaşık 440x250px boyutlarında olmalıdır.', // Actions - 'actions' => 'Aksiyonlar', + 'actions' => 'İşlemler', 'view' => 'Görüntüle', - 'view_all' => 'Hepsini Görüntüle', + 'view_all' => 'Hepsini Göster', 'create' => 'Oluştur', 'update' => 'Güncelle', 'edit' => 'Düzenle', @@ -47,31 +47,33 @@ return [ 'sort_descending' => 'Azalan Sıralama', 'sort_name' => 'İsim', 'sort_created_at' => 'Oluşturulma Tarihi', - 'sort_updated_at' => 'Güncellenme Tarihi', + 'sort_updated_at' => 'Güncelleme Tarihi', // Misc 'deleted_user' => 'Silinmiş Kullanıcı', - 'no_activity' => 'Gösterilecek aktivite yok', - 'no_items' => 'Kullanılabilir öge yok', + 'no_activity' => 'Gösterilecek eylem bulunamadı', + 'no_items' => 'Herhangi bir öge bulunamadı', 'back_to_top' => 'Başa dön', - 'toggle_details' => 'Detayları değiştir', - 'toggle_thumbnails' => 'Küçük resimleri değiştir', + 'toggle_details' => 'Detayları Göster/Gizle', + 'toggle_thumbnails' => 'Ön İzleme Görsellerini Göster/Gizle', 'details' => 'Detaylar', - 'grid_view' => 'Grid görünümü', - 'list_view' => 'Liste görünümü', + 'grid_view' => 'Izgara Görünümü', + 'list_view' => 'Liste Görünümü', 'default' => 'Varsayılan', - 'breadcrumb' => 'Sayfa İşaretleri Yolu', + 'breadcrumb' => 'Gezinti Menüsü', // Header - 'profile_menu' => 'Tercih menüsü', + 'profile_menu' => 'Profil Menüsü', 'view_profile' => 'Profili Görüntüle', 'edit_profile' => 'Profili Düzenle', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Bilgi', 'tab_content' => 'İçerik', // Email Content - 'email_action_help' => 'Eğer ":actionText" butonuna tıklamakta zorluk çekiyorsanız, aşağıda bulunan linki kopyalayıp tarayıcınıza yapıştırabilirsiniz.', - 'email_rights' => 'Bütün hakları saklıdır', + 'email_action_help' => '":actionText" butonuna tıklamada sorun yaşıyorsanız, aşağıda bulunan bağlantıyı kopyalayıp tarayıcınıza yapıştırın:', + 'email_rights' => 'Tüm hakları saklıdır', ]; diff --git a/resources/lang/tr/components.php b/resources/lang/tr/components.php index d52f2d006..4f1573541 100644 --- a/resources/lang/tr/components.php +++ b/resources/lang/tr/components.php @@ -6,28 +6,28 @@ return [ // Image Manager 'image_select' => 'Görsel Seç', - 'image_all' => 'Tümü', - 'image_all_title' => 'Tüm görselleri temizle', + 'image_all' => 'Hepsi', + 'image_all_title' => 'Bütün görselleri görüntüle', 'image_book_title' => 'Bu kitaba ait görselleri görüntüle', 'image_page_title' => 'Bu sayfaya ait görselleri görüntüle', - 'image_search_hint' => 'Görsel adı ile ara', + 'image_search_hint' => 'Görsel adıyla ara', 'image_uploaded' => ':uploadedDate tarihinde yüklendi', - 'image_load_more' => 'Daha Fazla ', + 'image_load_more' => 'Devamını Göster', 'image_image_name' => 'Görsel Adı', - 'image_delete_used' => 'Bu görsel aşağıda bulunan görsellerde kullanılmış.', - 'image_delete_confirm' => 'Gerçekten bu görseli silmek istiyorsanız sil tuşuna basınız.', + 'image_delete_used' => 'Bu görsel aşağıda bulunan sayfalarda kullanılmış.', + 'image_delete_confirm' => 'Bu görseli silmek istediğinize emin misiniz?', 'image_select_image' => 'Görsel Seç', - 'image_dropzone' => 'Görselleri buraya sürükle veya seçmek için buraya tıkla', + 'image_dropzone' => 'Görselleri sürükleyin ya da seçin', 'images_deleted' => 'Görseller Silindi', - 'image_preview' => 'Görsel Önizleme', + 'image_preview' => 'Görsel Ön İzlemesi', 'image_upload_success' => 'Görsel başarıyla yüklendi', - 'image_update_success' => 'Görsel başarıyla güncellendi', + 'image_update_success' => 'Görsel detayları başarıyla güncellendi', 'image_delete_success' => 'Görsel başarıyla silindi', 'image_upload_remove' => 'Kaldır', // Code Editor - 'code_editor' => 'Kodu Güncelle', - 'code_language' => 'Kod Dil', + 'code_editor' => 'Kodu Düzenle', + 'code_language' => 'Kod Dili', 'code_content' => 'Kod İçeriği', 'code_save' => 'Kodu Kaydet', ]; diff --git a/resources/lang/tr/entities.php b/resources/lang/tr/entities.php index 1163d09f0..df0dadb89 100644 --- a/resources/lang/tr/entities.php +++ b/resources/lang/tr/entities.php @@ -7,70 +7,70 @@ return [ // Shared 'recently_created' => 'Yakın Zamanda Oluşturuldu', - 'recently_created_pages' => 'Yakın Zamanda Oluşturulmuş Sayfalar', - 'recently_updated_pages' => 'Yakın Zamanda Güncellenmiş Sayfalar', - 'recently_created_chapters' => 'Yakın Zamanda Oluşturulmuş Bölümler', - 'recently_created_books' => 'Yakın Zamanda Olşturulmuş Kitaplar', - 'recently_created_shelves' => 'Yakın Zamanda Oluşturulmuş Kitaplıklar', + 'recently_created_pages' => 'Yakın Zamanda Oluşturulan Sayfalar', + 'recently_updated_pages' => 'Yakın Zamanda Güncellenen Sayfalar', + 'recently_created_chapters' => 'Yakın Zamanda Oluşturulan Bölümler', + 'recently_created_books' => 'Yakın Zamanda Oluşturulan Kitaplar', + 'recently_created_shelves' => 'Yakın Zamanda Oluşturulan Kitaplıklar', 'recently_update' => 'Yakın Zamanda Güncellenmiş', 'recently_viewed' => 'Yakın Zamanda Görüntülenmiş', 'recent_activity' => 'Son Hareketler', 'create_now' => 'Hemen bir tane oluştur', 'revisions' => 'Revizyonlar', 'meta_revision' => 'Revizyon #:revisionCount', - 'meta_created' => 'Oluşturuldu :timeLength', - 'meta_created_name' => ':user tarafından :timeLength tarihinde oluşturuldu', - 'meta_updated' => 'Güncellendi :timeLength', - 'meta_updated_name' => ':user tarafından :timeLength tarihinde güncellendi', - 'entity_select' => 'Öğe Seçme', + 'meta_created' => ':timeLength Oluşturuldu', + 'meta_created_name' => ':user tarafından :timeLength oluşturuldu', + 'meta_updated' => ':timeLength güncellendi', + 'meta_updated_name' => ':user tarafından :timeLength güncellendi', + 'entity_select' => 'Öge Seçimi', 'images' => 'Görseller', 'my_recent_drafts' => 'Son Taslaklarım', - 'my_recently_viewed' => 'Son Görüntülemelerim', + 'my_recently_viewed' => 'Son Görüntülediklerim', 'no_pages_viewed' => 'Herhangi bir sayfa görüntülemediniz', 'no_pages_recently_created' => 'Yakın zamanda bir sayfa oluşturulmadı', 'no_pages_recently_updated' => 'Yakın zamanda bir sayfa güncellenmedi', 'export' => 'Dışa Aktar', - 'export_html' => 'Contained Web Dosyası', + 'export_html' => 'Web Dosyası', 'export_pdf' => 'PDF Dosyası', 'export_text' => 'Düz Metin Dosyası', // Permissions and restrictions 'permissions' => 'İzinler', - 'permissions_intro' => 'Etkinleştirildikten sonra bu izinler diğer diğer bütün izinlerden öncelikli olacaktır.', + 'permissions_intro' => 'Etkinleştirildikten sonra bu izinler, diğer bütün izinlerden öncelikli olacaktır.', 'permissions_enable' => 'Özelleştirilmiş Yetkileri Etkinleştir', 'permissions_save' => 'İzinleri Kaydet', // Search 'search_results' => 'Arama Sonuçları', 'search_total_results_found' => ':count sonuç bulundu |:count toplam sonuç bulundu', - 'search_clear' => 'Aramaları Temizle', - 'search_no_pages' => 'Bu aramayla herhangi bir sonuç eşleşmedi', - 'search_for_term' => ':term için ara', + 'search_clear' => 'Aramayı Temizle', + 'search_no_pages' => 'Bu aramayla ilgili herhangi bir sayfa bulunamadı', + 'search_for_term' => ':term için Ara', 'search_more' => 'Daha Fazla Sonuç', 'search_filters' => 'Arama Filtreleri', 'search_content_type' => 'İçerik Türü', 'search_exact_matches' => 'Tam Eşleşmeler', 'search_tags' => 'Etiket Aramaları', 'search_options' => 'Ayarlar', - 'search_viewed_by_me' => 'Benim tarafımdan görüntülendi', - 'search_not_viewed_by_me' => 'Benim tarafımdan görüntülenmedi', - 'search_permissions_set' => 'İzinler ayarlandı', - 'search_created_by_me' => 'Benim tarafımdan oluşturuldu', - 'search_updated_by_me' => 'Benim tarafımdan güncellendi', + 'search_viewed_by_me' => 'Görüntülediklerim', + 'search_not_viewed_by_me' => 'Görüntülemediklerim', + 'search_permissions_set' => 'İzinler ayarlanmış', + 'search_created_by_me' => 'Oluşturduklarım', + 'search_updated_by_me' => 'Güncellediklerim', 'search_date_options' => 'Tarih Seçenekleri', 'search_updated_before' => 'Önce güncellendi', 'search_updated_after' => 'Sonra güncellendi', 'search_created_before' => 'Önce oluşturuldu', 'search_created_after' => 'Sonra oluşturuldu', - 'search_set_date' => 'Tarih Ayarla', + 'search_set_date' => 'Tarihi Ayarla', 'search_update' => 'Aramayı Güncelle', // Shelves 'shelf' => 'Kitaplık', 'shelves' => 'Kitaplıklar', - 'x_shelves' => ':count Kitaplık|:count Kitaplıklar', + 'x_shelves' => ':count Kitaplık|:count Kitaplık', 'shelves_long' => 'Kitaplıklar', - 'shelves_empty' => 'Hiç kitaplık oluşturulmadı', + 'shelves_empty' => 'Hiç kitaplık oluşturulmamış', 'shelves_create' => 'Yeni Kitaplık Oluştur', 'shelves_popular' => 'Popüler Kitaplıklar', 'shelves_new' => 'Yeni Kitaplıklar', @@ -80,28 +80,28 @@ return [ 'shelves_save' => 'Kitaplığı Kaydet', 'shelves_books' => 'Bu kitaplıktaki kitaplar', 'shelves_add_books' => 'Bu kitaplığa kitap ekle', - 'shelves_drag_books' => 'Bu kitaplığa kitap eklemek için kitapları buraya sürükle', - 'shelves_empty_contents' => 'Bu kitaplığa henüz hiç bir kitap atanmamış', - 'shelves_edit_and_assign' => 'Kitaplığa kitap eklemek için güncelle', - 'shelves_edit_named' => ':name Kitaplığını Güncelle', - 'shelves_edit' => 'Kitaplığı Güncelle', + 'shelves_drag_books' => 'Bu kitaplığa eklemek istediğin kitapları buraya sürükle', + 'shelves_empty_contents' => 'Bu kitaplıkta hiç kitap bulunamadı', + 'shelves_edit_and_assign' => 'Kitap eklemek için kitaplığı düzenleyin', + 'shelves_edit_named' => ':name Kitaplığını Düzenle', + 'shelves_edit' => 'Kitaplığı Düzenle', 'shelves_delete' => 'Kitaplığı Sil', 'shelves_delete_named' => ':name Kitaplığını Sil', - 'shelves_delete_explain' => "Bu işlem :name kitaplığını silecektir. İçerdiği kitaplar silinmeyecektir.", - 'shelves_delete_confirmation' => 'Bu kitaplığı silmek istediğinizden emin misiniz?', + 'shelves_delete_explain' => "Bu işlem ':name' kitaplığını silecektir ancak içerdiği kitaplara dokunulmayacaktır.", + 'shelves_delete_confirmation' => 'Bu kitaplığı silmek istediğinize emin misiniz?', 'shelves_permissions' => 'Kitaplık İzinleri', 'shelves_permissions_updated' => 'Kitaplık İzinleri Güncellendi', 'shelves_permissions_active' => 'Kitaplık İzinleri Aktif', 'shelves_copy_permissions_to_books' => 'İzinleri Kitaplara Kopyala', 'shelves_copy_permissions' => 'İzinleri Kopyala', - 'shelves_copy_permissions_explain' => 'Bu işlem sonucunda kitaplığınızın izinleri içerdiği kitaplara da aynen uygulanır. Aktifleştirmeden bu kitaplığa ait izinleri kaydettiğinizden emin olun.', + 'shelves_copy_permissions_explain' => 'Bu işlem sonucunda kitaplığınızın izinleri, içerdiği kitaplara da aynen uygulanır. Aktifleştirmeden önce bu kitaplığa ait izinleri kaydettiğinizden emin olun.', 'shelves_copy_permission_success' => 'Kitaplık izinleri :count adet kitaba kopyalandı', // Books 'book' => 'Kitap', 'books' => 'Kitaplar', - 'x_books' => ':count Kitap|:count Kitaplar', - 'books_empty' => 'Hiç kitap oluşturulmadı', + 'x_books' => ':count Kitap|:count Kitap', + 'books_empty' => 'Hiç kitap oluşturulmamış', 'books_popular' => 'Popüler Kitaplar', 'books_recent' => 'En Son Kitaplar', 'books_new' => 'Yeni Kitaplar', @@ -110,19 +110,19 @@ return [ 'books_new_empty' => 'En yeni kitaplar burada görüntülenecek.', 'books_create' => 'Yeni Kitap Oluştur', 'books_delete' => 'Kitabı Sil', - 'books_delete_named' => ':bookName kitabını sil', - 'books_delete_explain' => 'Bu işlem \':bookName\' kitabını silecek. Bütün sayfa ve bölümler silinecektir.', - 'books_delete_confirmation' => 'Bu kitabı silmek istediğinizden emin misiniz?', - 'books_edit' => 'Kitabı Güncelle', - 'books_edit_named' => ':bookName Kitabını Güncelle', + 'books_delete_named' => ':bookName Kitabını Sil', + 'books_delete_explain' => 'Bu işlem \':bookName\' kitabını silecektir. Ayrıca kitaba ait bütün sayfalar ve bölümler de silinecektir.', + 'books_delete_confirmation' => 'Bu kitabı silmek istediğinize emin misiniz?', + 'books_edit' => 'Kitabı Düzenle', + 'books_edit_named' => ':bookName Kitabını Düzenle', 'books_form_book_name' => 'Kitap Adı', 'books_save' => 'Kitabı Kaydet', 'books_permissions' => 'Kitap İzinleri', 'books_permissions_updated' => 'Kitap İzinleri Güncellendi', - 'books_empty_contents' => 'Bu kitaba ait sayfa veya bölüm oluşturulmadı.', - 'books_empty_create_page' => 'Yeni sayfa oluştur', + 'books_empty_contents' => 'Bu kitaba ait sayfa veya bölüm oluşturulmamış.', + 'books_empty_create_page' => 'Yeni bir sayfa oluştur', 'books_empty_sort_current_book' => 'Mevcut kitabı sırala', - 'books_empty_add_chapter' => 'Yeni bölüm ekle', + 'books_empty_add_chapter' => 'Yeni bir bölüm ekle', 'books_permissions_active' => 'Kitap İzinleri Aktif', 'books_search_this' => 'Bu kitapta ara', 'books_navigation' => 'Kitap Navigasyonu', @@ -130,7 +130,7 @@ return [ 'books_sort_named' => ':bookName Kitabını Sırala', 'books_sort_name' => 'İsme Göre Sırala', 'books_sort_created' => 'Oluşturulma Tarihine Göre Sırala', - 'books_sort_updated' => 'Güncellenme Tarihine Göre Sırala', + 'books_sort_updated' => 'Güncelleme Tarihine Göre Sırala', 'books_sort_chapters_first' => 'Önce Bölümler', 'books_sort_chapters_last' => 'En Son Bölümler', 'books_sort_show_other' => 'Diğer Kitapları Göster', @@ -139,67 +139,67 @@ return [ // Chapters 'chapter' => 'Bölüm', 'chapters' => 'Bölümler', - 'x_chapters' => ':count Bölüm|:count Bölümler', + 'x_chapters' => ':count Bölüm|:count Bölüm', 'chapters_popular' => 'Popüler Bölümler', 'chapters_new' => 'Yeni Bölüm', 'chapters_create' => 'Yeni Bölüm Oluştur', 'chapters_delete' => 'Bölümü Sil', 'chapters_delete_named' => ':chapterName Bölümünü Sil', - 'chapters_delete_explain' => 'Bu işlem \':chapterName\' kitabını silecek. Bütün sayfalar silinecek ve direkt olarak ana kitab eklenecektir.', - 'chapters_delete_confirm' => 'Bölümü silmek istediğinizden emin misiniz?', - 'chapters_edit' => 'Bölümü Güncelle', - 'chapters_edit_named' => ':chapterName Bölümünü Güncelle', + 'chapters_delete_explain' => 'Bu işlem sonunda \':chapterName\' bölümü silinecek ve bu bölüme ait bütün sayfalar direkt olarak ana kitaba aktarılacaktır.', + 'chapters_delete_confirm' => 'Bölümü silmek istediğinize emin misiniz?', + 'chapters_edit' => 'Bölümü Düzenle', + 'chapters_edit_named' => ':chapterName Bölümünü Düzenle', 'chapters_save' => 'Bölümü Kaydet', 'chapters_move' => 'Bölümü Taşı', 'chapters_move_named' => ':chapterName Bölümünü Taşı', - 'chapter_move_success' => 'Bölüm :bookName Kitabına Taşındı', + 'chapter_move_success' => 'Bölüm, :bookName kitabına taşındı', 'chapters_permissions' => 'Bölüm İzinleri', - 'chapters_empty' => 'Bu bölümde henüz bir sayfa yok.', + 'chapters_empty' => 'Bu bölümde henüz bir sayfa bulunmuyor.', 'chapters_permissions_active' => 'Bölüm İzinleri Aktif', 'chapters_permissions_success' => 'Bölüm İzinleri Güncellendi', - 'chapters_search_this' => 'Bu bölümü ara', + 'chapters_search_this' => 'Bu bölümde ara', // Pages 'page' => 'Sayfa', 'pages' => 'Sayfalar', - 'x_pages' => ':count Sayfa|:count Sayfalar', + 'x_pages' => ':count Sayfa|:count Sayfa', 'pages_popular' => 'Popüler Sayfalar', 'pages_new' => 'Yeni Sayfa', 'pages_attachments' => 'Ekler', 'pages_navigation' => 'Sayfa Navigasyonu', 'pages_delete' => 'Sayfayı Sil', 'pages_delete_named' => ':pageName Sayfasını Sil', - 'pages_delete_draft_named' => ':pageName Taslak Sayfasını Sil', - 'pages_delete_draft' => 'Taslak Sayfayı Sil', + 'pages_delete_draft_named' => ':pageName Sayfa Taslağını Sil', + 'pages_delete_draft' => 'Sayfa Taslağını Sil', 'pages_delete_success' => 'Sayfa silindi', - 'pages_delete_draft_success' => 'Taslak sayfa silindi', - 'pages_delete_confirm' => 'Bu sayfayı silmek istediğinizden emin misiniz?', - 'pages_delete_draft_confirm' => 'Bu taslak sayfayı silmek istediğinizden emin misiniz?', + 'pages_delete_draft_success' => 'Sayfa taslağı silindi', + 'pages_delete_confirm' => 'Bu sayfayı silmek istediğinize emin misiniz?', + 'pages_delete_draft_confirm' => 'Bu sayfa taslağını silmek istediğinize emin misiniz?', 'pages_editing_named' => ':pageName Sayfası Düzenleniyor', 'pages_edit_draft_options' => 'Taslak Seçenekleri', 'pages_edit_save_draft' => 'Taslağı Kaydet', - 'pages_edit_draft' => 'Taslak Sayfasını Düzenle', + 'pages_edit_draft' => 'Sayfa Taslağını Düzenle', 'pages_editing_draft' => 'Taslak Düzenleniyor', 'pages_editing_page' => 'Sayfa Düzenleniyor', 'pages_edit_draft_save_at' => 'Taslak kaydedildi ', - 'pages_edit_delete_draft' => 'Taslağı Sl', + 'pages_edit_delete_draft' => 'Taslağı Sil', 'pages_edit_discard_draft' => 'Taslağı Yoksay', - 'pages_edit_set_changelog' => 'Değişiklik Logunu Kaydet', - 'pages_edit_enter_changelog_desc' => 'Yaptığınız değişiklikler hakkında kısa bir bilgilendirme ekleyin', - 'pages_edit_enter_changelog' => 'Değişim Günlüğü Ekleyin', + 'pages_edit_set_changelog' => 'Değişim Günlüğünü Ayarla', + 'pages_edit_enter_changelog_desc' => 'Yaptığınız değişiklikler hakkında kısa bir açıklama girin', + 'pages_edit_enter_changelog' => 'Değişim Günlüğünü Yazın', 'pages_save' => 'Sayfayı Kaydet', 'pages_title' => 'Sayfa Başlığı', 'pages_name' => 'Sayfa İsmi', - 'pages_md_editor' => 'Editör', - 'pages_md_preview' => 'Önizleme', + 'pages_md_editor' => 'Düzenleyici', + 'pages_md_preview' => 'Ön İzleme', 'pages_md_insert_image' => 'Görsel Ekle', - 'pages_md_insert_link' => 'Öge Linki Ekle', + 'pages_md_insert_link' => 'Öge Bağlantısı Ekle', 'pages_md_insert_drawing' => 'Çizim Ekle', - 'pages_not_in_chapter' => 'Sayfa Bu Bölümde Değil', + 'pages_not_in_chapter' => 'Bu sayfa, bir bölüme ait değil', 'pages_move' => 'Sayfayı Taşı', - 'pages_move_success' => 'Sayfa ":parentName"\'a taşındı', + 'pages_move_success' => 'Sayfa şuraya taşındı: :parentName', 'pages_copy' => 'Sayfayı Kopyala', - 'pages_copy_desination' => 'Kopyalanacak Hedef', + 'pages_copy_desination' => 'Kopyalama Hedefi', 'pages_copy_success' => 'Sayfa başarıyla kopyalandı', 'pages_permissions' => 'Sayfa İzinleri', 'pages_permissions_success' => 'Sayfa izinleri güncellendi', @@ -207,33 +207,33 @@ return [ 'pages_revisions' => 'Sayfa Revizyonları', 'pages_revisions_named' => ':pageName için Sayfa Revizyonları', 'pages_revision_named' => ':pageName için Sayfa Revizyonu', - 'pages_revisions_created_by' => 'Oluşturan', + 'pages_revisions_created_by' => 'Revize Eden', 'pages_revisions_date' => 'Revizyon Tarihi', 'pages_revisions_number' => '#', 'pages_revisions_numbered' => 'Revizyon #:id', 'pages_revisions_numbered_changes' => 'Revizyon #:id Değişiklikleri', 'pages_revisions_changelog' => 'Değişim Günlüğü', 'pages_revisions_changes' => 'Değişiklikler', - 'pages_revisions_current' => 'Mevcut Versiyon', - 'pages_revisions_preview' => 'Önizleme', - 'pages_revisions_restore' => 'Kurtar', - 'pages_revisions_none' => 'Bu sayfaya ait revizyon yok', - 'pages_copy_link' => 'Linki kopyala', + 'pages_revisions_current' => 'Şimdiki Sürüm', + 'pages_revisions_preview' => 'Ön İzleme', + 'pages_revisions_restore' => 'Geri Dön', + 'pages_revisions_none' => 'Bu sayfaya ait herhangi bir revizyon bulunamadı', + 'pages_copy_link' => 'Bağlantıyı kopyala', 'pages_edit_content_link' => 'İçeriği Düzenle', 'pages_permissions_active' => 'Sayfa İzinleri Aktif', - 'pages_initial_revision' => 'İlk Yayın', + 'pages_initial_revision' => 'İlk yayın', 'pages_initial_name' => 'Yeni Sayfa', - 'pages_editing_draft_notification' => 'Şu anda :timeDiff tarhinde kaydedilmiş olan taslağı düzenlemektesiniz.', - 'pages_draft_edited_notification' => 'Bu sayfa son girişinizden bu yana güncellendi. Değişiklikleri yoksayıp, kaydetmeden çıkmanız önerilir.', + 'pages_editing_draft_notification' => 'Şu anda en son :timeDiff tarihinde kaydedilmiş olan taslağı düzenliyorsunuz.', + 'pages_draft_edited_notification' => 'Bu sayfa o zamandan bu zamana güncellenmiş, bu nedenle bu taslağı yok saymanız önerilir.', 'pages_draft_edit_active' => [ - 'start_a' => ':count kullanıcı bu sayfayı düzenlemeye başladı', - 'start_b' => ':userName kullanıcısı bu sayfayı düzenlemeye başladı', + 'start_a' => ':count kullanıcı, bu sayfayı düzenlemeye başladı', + 'start_b' => ':userName, bu sayfayı düzenlemeye başladı', 'time_a' => 'sayfa son güncellendiğinden beri', 'time_b' => 'son :minCount dakikada', - 'message' => ':start :time. Birbirinizin düzenlemelerinin çakışmamasına dikkat edin!', + 'message' => ':start :time. Düzenlemelerinizin çakışmamasına dikkat edin!', ], - 'pages_draft_discarded' => 'Taslak yok sayıldı, editör mevcut sayfa içeriği ile güncellendi', - 'pages_specific' => 'Özel Sayfa', + 'pages_draft_discarded' => 'Taslak yok sayıldı. Düzenleyici, mevcut sayfa içeriği kullanılarak güncellendi', + 'pages_specific' => 'Spesifik Sayfa', 'pages_is_template' => 'Sayfa Şablonu', // Editor Sidebar @@ -244,71 +244,71 @@ return [ 'tag' => 'Etiket', 'tags' => 'Etiketler', 'tag_name' => 'Etiket İsmi', - 'tag_value' => 'Etiket İçeriği (Opsiyonel)', - 'tags_explain' => "İçeriğini daha iyi kategorize etmek için bazı etiketler ekle. Etiketlere değer atayarak daha derin bir organizasyon yapısına sahip olabilirsin.", + 'tag_value' => 'Etiket Değeri (Opsiyonel)', + 'tags_explain' => "İçeriğinizi daha iyi kategorize etmek için etiket ekleyin. Etiketlere değer atayarak daha derinlemesine bir düzen elde edebilirsiniz.", 'tags_add' => 'Başka etiket ekle', - 'tags_remove' => 'Bu Etiketi Sil', + 'tags_remove' => 'Bu etiketi sil', 'attachments' => 'Ekler', - 'attachments_explain' => 'Sayfanızda göstermek için bazı dosyalar yükleyin veya bazı bağlantılar ekleyin. Bunlar sayfanın sidebarında görülebilir.', + 'attachments_explain' => 'Sayfanızda göstermek için dosyalar yükleyin veya bağlantılar ekleyin. Bunlar, sayfaya ait yan menüde gösterilecektir.', 'attachments_explain_instant_save' => 'Burada yapılan değişiklikler anında kaydedilir.', 'attachments_items' => 'Eklenmiş Ögeler', 'attachments_upload' => 'Dosya Yükle', 'attachments_link' => 'Link Ekle', - 'attachments_set_link' => 'Link Düzenle', - 'attachments_delete_confirm' => 'Eki gerçekten silmek istiyor musunuz?', - 'attachments_dropzone' => 'Dosyaları buraya sürükle veya eklemek için buraya tıkla', - 'attachments_no_files' => 'Hiç bir dosya yüklenmedi', - 'attachments_explain_link' => 'Eğer dosya yüklememeyi tercih ederseniz link ekleyebilirsiniz. Bu başka bir sayfaya veya buluttaki bir dosyanın linki olabilir.', + 'attachments_set_link' => 'Bağlantıyı Ata', + 'attachments_delete_confirm' => 'Eki silmek istediğinize emin misiniz?', + 'attachments_dropzone' => 'Dosyaları sürükleyin veya seçin', + 'attachments_no_files' => 'Hiçbir dosya yüklenmedi', + 'attachments_explain_link' => 'Eğer dosya yüklememeyi tercih ederseniz bağlantı ekleyebilirsiniz. Bu bağlantı başka bir sayfanın veya bulut depolamadaki bir dosyanın bağlantısı olabilir.', 'attachments_link_name' => 'Bağlantı Adı', - 'attachment_link' => 'Ek linki', - 'attachments_link_url' => 'Dosya linki', - 'attachments_link_url_hint' => 'Dosyanın veya sitenin url adres', + 'attachment_link' => 'Ek bağlantısı', + 'attachments_link_url' => 'Dosya bağlantısı', + 'attachments_link_url_hint' => 'Dosyanın veya sitenin url adresi', 'attach' => 'Ekle', 'attachments_edit_file' => 'Dosyayı Düzenle', 'attachments_edit_file_name' => 'Dosya Adı', - 'attachments_edit_drop_upload' => 'Dosyaları sürükle veya yüklemek için buraya tıkla', - 'attachments_order_updated' => 'Ek sırası güncellendi', + 'attachments_edit_drop_upload' => 'Üzerine yazılacak dosyaları sürükleyin veya seçin', + 'attachments_order_updated' => 'Ek sıralaması güncellendi', 'attachments_updated_success' => 'Ek detayları güncellendi', 'attachments_deleted' => 'Ek silindi', 'attachments_file_uploaded' => 'Dosya başarıyla yüklendi', 'attachments_file_updated' => 'Dosya başarıyla güncellendi', - 'attachments_link_attached' => 'Link sayfaya başarıyla eklendi', + 'attachments_link_attached' => 'Bağlantı, sayfaya başarıyla eklendi', 'templates' => 'Şablonlar', - 'templates_set_as_template' => 'Sayfa bir şablondur', - 'templates_explain_set_as_template' => 'Bu sayfayı şablon olarak seçebilirsiniz. Böylece taslağın içeriği diğer sayfaları oluştururken düzenlenebilir. Eğer yetkileri varsa diğer kullanıcılar da bu sayfayı görüntülerken bu şablonu kullanabilirler.', + 'templates_set_as_template' => 'Bu sayfa, bir şablondur', + 'templates_explain_set_as_template' => 'Başka sayfalar oluştururken bu sayfanın içeriğini kullanabilmek için bu sayfayı bir şablon olarak ayarlayabilirsiniz. Bu sayfayı görüntüleme yetkisi olan kullanıcılar da bu şablonu kullanabileceklerdir.', 'templates_replace_content' => 'Sayfa içeriğini değiştir', 'templates_append_content' => 'Sayfa içeriğine ekle', 'templates_prepend_content' => 'Sayfa içeriğinin başına ekle', // Profile View - 'profile_user_for_x' => 'Kullanıcı :time', + 'profile_user_for_x' => 'Üyelik süresi: :time', 'profile_created_content' => 'Oluşturulan İçerik', - 'profile_not_created_pages' => ':userName herhangi bir sayfa oluşturmadı', - 'profile_not_created_chapters' => ':userName herhangi bir bölüm oluşturmadı', - 'profile_not_created_books' => ':userName herhangi bir kitap oluşturmadı', - 'profile_not_created_shelves' => ':userName herhangi bir kitaplık oluşturmadı', + 'profile_not_created_pages' => ':userName herhangi bir sayfa oluşturmamış', + 'profile_not_created_chapters' => ':userName herhangi bir bölüm oluşturmamış', + 'profile_not_created_books' => ':userName herhangi bir kitap oluşturmamış', + 'profile_not_created_shelves' => ':userName herhangi bir kitaplık oluşturmamış', // Comments 'comment' => 'Yorum', 'comments' => 'Yorumlar', 'comment_add' => 'Yorum Ekle', - 'comment_placeholder' => 'Buraya yorum ekle', - 'comment_count' => '{0} Yorum Yok|{1} 1 Yorum|[2,*] :count Yorun', - 'comment_save' => 'Yorum Kaydet', - 'comment_saving' => 'Yorum kaydediliyor...', + 'comment_placeholder' => 'Buraya bir yorum yazın', + 'comment_count' => '{0} Yorum Yapılmamış|{1} 1 Yorum|[2,*] :count Yorum', + 'comment_save' => 'Yorumu Gönder', + 'comment_saving' => 'Yorum gönderiliyor...', 'comment_deleting' => 'Yorum siliniyor...', 'comment_new' => 'Yeni Yorum', - 'comment_created' => 'yorum yaptı :createDiff', - 'comment_updated' => ':username tarafından :updateDiff önce güncellendi', + 'comment_created' => ':createDiff yorum yaptı', + 'comment_updated' => ':username tarafından :updateDiff güncellendi', 'comment_deleted_success' => 'Yorum silindi', - 'comment_created_success' => 'Yorum eklendi', + 'comment_created_success' => 'Yorum gönderildi', 'comment_updated_success' => 'Yorum güncellendi', - 'comment_delete_confirm' => 'Bu yorumu silmek istediğinizden emin misiniz?', + 'comment_delete_confirm' => 'Bu yorumu silmek istediğinize emin misiniz?', 'comment_in_reply_to' => ':commentId yorumuna yanıt olarak', // Revision - 'revision_delete_confirm' => 'Bu revizyonu silmek istediğinizden emin misiniz?', - 'revision_restore_confirm' => 'Bu revizyonu yeniden yüklemek istediğinizden emin misiniz? Mevcut sayfa içeriği değiştirilecektir.', + 'revision_delete_confirm' => 'Bu revizyonu silmek istediğinize emin misiniz?', + 'revision_restore_confirm' => 'Bu revizyonu yeniden yüklemek istediğinize emin misiniz? Sayfanın şu anki içeriği değiştirilecektir.', 'revision_delete_success' => 'Revizyon silindi', - 'revision_cannot_delete_latest' => 'Son revizyon silinemez.' + 'revision_cannot_delete_latest' => 'Son revizyonu silemezsiniz.' ]; \ No newline at end of file diff --git a/resources/lang/tr/errors.php b/resources/lang/tr/errors.php index 50688219e..af2a47623 100644 --- a/resources/lang/tr/errors.php +++ b/resources/lang/tr/errors.php @@ -5,44 +5,44 @@ return [ // Permissions - 'permission' => 'Bu sayfaya erişme yetkiniz yok.', - 'permissionJson' => 'Bu işlemi yapmak için yetkiniz yo.', + 'permission' => 'Bu sayfaya erişim izniniz bulunmuyor.', + 'permissionJson' => 'Bu işlemi yapmaya yetkiniz bulunmuyor.', // Auth - 'error_user_exists_different_creds' => ':email adresi farklı kullanıcı bilgileri ile zaten kullanımda.', - 'email_already_confirmed' => 'E-mail halihazırda onaylanmış, giriş yapmayı dene.', - 'email_confirmation_invalid' => 'Bu doğrulama tokenı daha önce kullanılmış veya geçerli değil, lütfen tekrar kayıt olmayı deneyin.', - 'email_confirmation_expired' => 'Doğrulama token\'ının süresi geçmiş, yeni bir mail gönderildi.', - 'email_confirmation_awaiting' => 'Kullanılan hesabın e-posta adresinin onaylanması gerekiyor', - 'ldap_fail_anonymous' => 'Anonim LDAP girişi başarısız oldu', - 'ldap_fail_authed' => 'Verdiğiniz bilgiler ile LDAP girişi başarısız oldu.', - 'ldap_extension_not_installed' => 'LDAP PHP eklentisi yüklenmedi', + 'error_user_exists_different_creds' => ':email e-posta adresine sahip bir kullanıcı zaten var.', + 'email_already_confirmed' => 'E-posta adresi zaten doğrulanmış, giriş yapmayı deneyin.', + 'email_confirmation_invalid' => 'Bu doğrulama kodu ya geçersiz ya da daha önce kullanılmış, lütfen tekrar kaydolmayı deneyin.', + 'email_confirmation_expired' => 'Doğrulama kodunun süresi doldu, yeni bir doğrulama kodu e-posta adresine gönderildi.', + 'email_confirmation_awaiting' => 'Bu hesaba ait e-posta adresinin doğrulanması gerekiyor', + 'ldap_fail_anonymous' => 'Anonim olarak gerçekleştirilmeye çalışılan LDAP erişimi başarısız oldu', + 'ldap_fail_authed' => 'Verilen bilgiler kullanılarak gerçekleştirilmeye çalışılan LDAP erişimi başarısız oldu', + 'ldap_extension_not_installed' => 'LDAP PHP eklentisi kurulu değil', 'ldap_cannot_connect' => 'LDAP sunucusuna bağlanılamadı, ilk bağlantı başarısız oldu', - 'saml_already_logged_in' => 'Zaten giriş yapıldı', - 'saml_user_not_registered' => ':name adlı kullanıcı kayıtlı değil ve otomatik kaydolma devre dışı', - 'saml_no_email_address' => 'Bu kullanıcı için, harici bir doğrulama siteminden elde edilen verilerde, bir e-posta adresi bulunamadı', - 'saml_invalid_response_id' => 'Harici doğrulama sistemi tarafından sağlanan bir veri talebi, bu uygulama tarafından başlatılan bir işlem tarafından tanınamadı. Giriş yaptıktan sonra geri dönmek bu soruna yol açabilir.', - 'saml_fail_authed' => ':system kullanarak giriş yapma başarısız, sistem başarılı bir doğrulama sağlamadı', - 'social_no_action_defined' => 'Bir aksiyon tanımlanmadı', - 'social_login_bad_response' => ":socialAccount girişi sırasında hata oluştu: \n:error", + 'saml_already_logged_in' => 'Zaten giriş yapılmış', + 'saml_user_not_registered' => ':name adlı kullanıcı kayıtlı değil ve otomatik kaydolma devre dışı bırakılmış', + 'saml_no_email_address' => 'Harici kimlik doğrulama sisteminden gelen veriler, bu kullanıcının e-posta adresini içermiyor', + 'saml_invalid_response_id' => 'Harici doğrulama sistemi tarafından sağlanan bir veri talebi, bu uygulama tarafından başlatılan bir işlem tarafından tanınamadı. Giriş yaptıktan sonra geri dönmek bu soruna yol açmış olabilir.', + 'saml_fail_authed' => ':system kullanarak giriş yapma başarısız oldu; sistem, başarılı bir kimlik doğrulama sağlayamadı', + 'social_no_action_defined' => 'Herhangi bir eylem tanımlanmamış', + 'social_login_bad_response' => ":socialAccount girişi sırasında bir hata meydana geldi: \n:error", 'social_account_in_use' => 'Bu :socialAccount zaten kullanımda, :socialAccount hesabıyla giriş yapmayı deneyin.', - 'social_account_email_in_use' => ':email adresi zaten kullanımda. Eğer zaten bir hesabınız varsa :socialAccount hesabınızı profil ayarları kısmından bağlayabilirsiniz.', - 'social_account_existing' => 'Bu :socialAccount zaten profilinize eklenmiş.', - 'social_account_already_used_existing' => 'Bu :socialAccount başka bir kullanıcı tarafından kullanılıyor.', - 'social_account_not_used' => 'Bu :socialAccount hesabı hiç bir kullanıcıya bağlı değil. Lütfen profil ayarlarına gidiniz ve bağlayınız. ', - 'social_account_register_instructions' => 'Hala bir hesabınız yoksa :socialAccount ile kayıt olabilirsiniz.', + 'social_account_email_in_use' => ':email e-posta adresi zaten kullanılıyor. Zaten bir hesabınız varsa, :socialAccount hesabınızı profil ayarlarınızdan mevcut hesabınıza bağlayabilirsiniz.', + 'social_account_existing' => 'Bu :socialAccount zaten hesabınıza bağlanmış.', + 'social_account_already_used_existing' => 'Bu :socialAccount, başka bir kullanıcı tarafından kullanılıyor.', + 'social_account_not_used' => 'Bu :socialAccount hesabı hiç bir kullanıcıya bağlanmamış. Lütfen profil ayarlarınızdan mevcut hesabınıza bağlayınız. ', + 'social_account_register_instructions' => 'Hâlâ bir hesabınız yoksa, :socialAccount aracılığıyla kaydolabilirsiniz.', 'social_driver_not_found' => 'Social driver bulunamadı', 'social_driver_not_configured' => ':socialAccount ayarlarınız doğru bir şekilde ayarlanmadı.', - 'invite_token_expired' => 'Davetiye linkinin süresi doldu. Bunun yerine parolanızı sıfırlamayı deneyebilirsiniz.', + 'invite_token_expired' => 'Davetiye bağlantısının süresi doldu. Bunun yerine parolanızı sıfırlamayı deneyebilirsiniz.', // System 'path_not_writable' => ':filePath dosya yolu yüklenemedi. Sunucuya yazılabilir olduğundan emin olun.', - 'cannot_get_image_from_url' => ':url\'den görsel alınamadı', - 'cannot_create_thumbs' => 'Sunucu küçük resimleri oluşturamadı. Lütfen GD PHP eklentisinin yüklü olduğundan emin olun.', - 'server_upload_limit' => 'Sunucu bu boyutta dosya yüklemenize izin vermiyor. Lütfen daha küçük boyutta dosya yüklemeyi deneyiniz.', - 'uploaded' => 'Sunucu bu boyutta dosya yüklemenize izin vermiyor. Lütfen daha küçük boyutta dosya yüklemeyi deneyiniz.', - 'image_upload_error' => 'Görsel yüklenirken bir hata oluştu', - 'image_upload_type_error' => 'Yüklemeye çalıştığınız dosya türü geçerli değildir', + 'cannot_get_image_from_url' => ':url adresindeki görsel alınamadı', + 'cannot_create_thumbs' => 'Sunucu, görsel ön izlemelerini oluşturamadı. Lütfen GD PHP eklentisinin kurulu olduğundan emin olun.', + 'server_upload_limit' => 'Sunucu bu boyutta dosya yüklemenize izin vermiyor. Lütfen daha küçük bir dosya deneyin.', + 'uploaded' => 'Sunucu bu boyutta dosya yüklemenize izin vermiyor. Lütfen daha küçük bir dosya deneyin.', + 'image_upload_error' => 'Görsel yüklenirken bir hata meydana geldi', + 'image_upload_type_error' => 'Yüklemeye çalıştığınız dosya türü geçersizdir', 'file_upload_timeout' => 'Dosya yüklemesi zaman aşımına uğradı', // Attachments @@ -50,11 +50,11 @@ return [ 'attachment_not_found' => 'Ek bulunamadı', // Pages - 'page_draft_autosave_fail' => 'Taslak kaydetme başarısız. Sayfanızı kaydetmeden önce internet bağlantınız olduğundan emin olun', - 'page_custom_home_deletion' => 'Bu sayfa anasayfa olarak ayarlandığı için silinemez', + 'page_draft_autosave_fail' => 'Taslak kaydetme başarısız oldu. Bu sayfayı kaydetmeden önce internet bağlantınız olduğundan emin olun', + 'page_custom_home_deletion' => 'Bu sayfa, "Ana Sayfa" olarak ayarlandığı için silinemez', // Entities - 'entity_not_found' => 'Eleman bulunamadı', + 'entity_not_found' => 'Öge bulunamadı', 'bookshelf_not_found' => 'Kitaplık bulunamadı', 'book_not_found' => 'Kitap bulunamadı', 'page_not_found' => 'Sayfa bulunamadı', @@ -69,35 +69,35 @@ return [ // Roles 'role_cannot_be_edited' => 'Bu rol düzenlenemez', - 'role_system_cannot_be_deleted' => 'Bu bir yönetici rolüdür ve silinemez', - 'role_registration_default_cannot_delete' => 'Bu rol varsayılan yönetici rolü olarak atandığı için silinemez ', - 'role_cannot_remove_only_admin' => 'Bu kullanıcı yönetici rolü olan tek kullanıcı olduğu için silinemez. Bu kullanıcıyı silmek için önce başka bir kullanıcıya yönetici rolü atayın.', + 'role_system_cannot_be_deleted' => 'Bu rol, bir sistem rolüdür ve silinemez', + 'role_registration_default_cannot_delete' => 'Bu rol, kaydolan üyelere varsayılan olarak atandığı için silinemez', + 'role_cannot_remove_only_admin' => 'Bu kullanıcı, yönetici rolü olan tek kullanıcı olduğu için silinemez. Bu kullanıcıyı silmek için önce başka bir kullanıcıya yönetici rolü atayın.', // Comments 'comment_list' => 'Yorumlar yüklenirken bir hata oluştu.', 'cannot_add_comment_to_draft' => 'Taslaklara yorum ekleyemezsiniz.', 'comment_add' => 'Yorum eklerken/güncellerken bir hata olıuştu.', 'comment_delete' => 'Yorum silinirken bir hata oluştu.', - 'empty_comment' => 'Boş bir yorum eklenemez.', + 'empty_comment' => 'Boş bir yorum ekleyemezsiniz.', // Error pages '404_page_not_found' => 'Sayfa Bulunamadı', 'sorry_page_not_found' => 'Üzgünüz, aradığınız sayfa bulunamıyor.', - 'sorry_page_not_found_permission_warning' => 'Görüntüleyemediğiniz bu sayfanın var olduğunu düşünüyorsanız, görüntüleme izniniz olmayabilir.', - 'return_home' => 'Anasayfaya dön', + 'sorry_page_not_found_permission_warning' => 'Bu sayfanın var olduğunu düşünüyorsanız, görüntüleme iznine sahip olmayabilirsiniz.', + 'return_home' => 'Ana sayfaya dön', 'error_occurred' => 'Bir Hata Oluştu', - 'app_down' => ':appName şu anda inaktif', - 'back_soon' => 'En kısa zamanda aktif hale gelecek.', + 'app_down' => ':appName şu anda erişilemez durumda', + 'back_soon' => 'En kısa sürede tekrar erişilebilir duruma gelecektir.', // API errors - 'api_no_authorization_found' => 'İstekte yetkilendirme anahtarı bulunamadı', - 'api_bad_authorization_format' => 'İstekte bir yetkilendirme anahtarı bulundu, ancak biçim yanlış görünüyor', + 'api_no_authorization_found' => 'Yapılan istekte, yetkilendirme anahtarı bulunamadı', + 'api_bad_authorization_format' => 'Yapılan istekte bir yetkilendirme anahtarı bulundu fakat doğru görünmüyor', 'api_user_token_not_found' => 'Sağlanan yetkilendirme anahtarı ile eşleşen bir API anahtarı bulunamadı', - 'api_incorrect_token_secret' => 'Kullanılan API anahtarı için sağlanan gizli anahtar doğru değil', + 'api_incorrect_token_secret' => 'Kullanılan API için sağlanan gizli anahtar doğru değil', 'api_user_no_api_permission' => 'Kullanılan API anahtarının sahibi API çağrısı yapmak için izne sahip değil', 'api_user_token_expired' => 'Kullanılan yetkilendirme anahtarının süresi doldu', // Settings & Maintenance - 'maintenance_test_email_failure' => 'Test e-postası gönderilirken hata oluştu:', + 'maintenance_test_email_failure' => 'Test e-postası gönderilirken bir hata meydana geldi:', ]; diff --git a/resources/lang/tr/passwords.php b/resources/lang/tr/passwords.php index 42e9ef2c7..ba1fd913f 100644 --- a/resources/lang/tr/passwords.php +++ b/resources/lang/tr/passwords.php @@ -6,10 +6,10 @@ */ return [ - 'password' => 'Parolanız en az 6 karakterden oluşmalı ve doğrulama parolası ile eşleşmelidir. ', - 'user' => "Bu e-mail adresi ile ilişkilendirilmiş bir kullanıcı bulamadık.", - 'token' => 'Parola yenileme tokeni geçerli değil.', - 'sent' => 'Parola sıfırlanma bağlantısını e-mail adresinize gönderdik!', - 'reset' => 'Parolanız sıfırlandı!', + 'password' => 'Şifreniz en az 6 karakterden oluşmalı ve her iki şifre de birbiri ile eşleşmelidir.', + 'user' => "Bu e-posta adresine sahip bir kullanıcı bulamadık.", + 'token' => 'Şifre sıfırlama anahtarı, bu e-posta adresi için geçersizdir.', + 'sent' => 'Şifre sıfırlama bağlantısını e-posta adresinize gönderdik!', + 'reset' => 'Şifreniz sıfırlandı!', ]; diff --git a/resources/lang/tr/settings.php b/resources/lang/tr/settings.php index 638796fa4..545c91fe0 100755 --- a/resources/lang/tr/settings.php +++ b/resources/lang/tr/settings.php @@ -9,108 +9,108 @@ return [ // Common Messages 'settings' => 'Ayarlar', 'settings_save' => 'Ayarları Kaydet', - 'settings_save_success' => 'Ayarlar Kaydedildi', + 'settings_save_success' => 'Ayarlar kaydedildi', // App Settings 'app_customization' => 'Özelleştirme', 'app_features_security' => 'Özellikler & Güvenlik', 'app_name' => 'Uygulama Adı', - 'app_name_desc' => 'Bu isim başlıkta ve sistem tarafında gönderilen tüm mesajlarda gösterilecektir.', + 'app_name_desc' => 'Bu isim, başlıkta ve sistem tarafından gönderilen bütün e-postalarda gösterilecektir.', 'app_name_header' => 'İsmi başlıkta göster', 'app_public_access' => 'Açık Erişim', - 'app_public_access_desc' => 'Bu özelliği aktif etmek giriş yapmamış misafir kullanıcıların sizin BookStack uygulamanıza erişmesini sağlar', - 'app_public_access_desc_guest' => 'Kayıtlı olmayan kullanıcılar için erişim yetkisi "Guest" kullanıcısı üzerinden düzenlenebilir.', + 'app_public_access_desc' => 'Bu özelliği aktifleştirmek, giriş yapmamış misafir kullanıcıların BookStack uygulamanıza erişimini sağlar.', + 'app_public_access_desc_guest' => 'Kayıtlı olmayan kullanıcılar için erişim yetkileri, "Guest" kullanıcısı üzerinden kontrol edilebilir.', 'app_public_access_toggle' => 'Açık erişime izin ver', - 'app_public_viewing' => 'Herkese açık görüntülenmeye izin verilsin mi?', - 'app_secure_images' => 'Daha Yüksek Güvenlikli Görsel Yüklemeleri', - 'app_secure_images_toggle' => 'Daha yüksek güveblikli görsel yüklemelerine izin ver', - 'app_secure_images_desc' => 'Performans sebepleri nedeniyle bütün görseller halka açık. Bu opsiyon rastgele ve tahmin edilmesi zor dizileri görsel linklerinin önüne ekler. Dizin indexlerinin kapalı olduğundan emin olun.', - 'app_editor' => 'Sayfa Editörü', - 'app_editor_desc' => 'Sayfa düzenlemesi yapılırken hangi editörün kullanılacağını seçin.', - 'app_custom_html' => 'Özel HTML Head İçeriği', - 'app_custom_html_desc' => 'Buraya eklenecek olan içerik taginin en sonuna eklenecektir. Bu stilleri override ederken veya analytics eklerken faydalı bir kullanım şeklidir.', - 'app_custom_html_disabled_notice' => 'Yapılan hatalı değişikliklerin geriye alınabilmesi için bu sayfada özel HTML head içeriği kapalı.', + 'app_public_viewing' => 'Herkese açık görüntülemeye izin verilsin mi?', + 'app_secure_images' => 'Daha Güvenli Görsel Yüklemeleri', + 'app_secure_images_toggle' => 'Daha güvenli görsel yüklemelerini aktifleştir', + 'app_secure_images_desc' => 'Bütün görseller, performans sebepleri nedeniyle herkes tarafından görüntülenebilir durumdadır. Bu seçeneği aktif ederseniz; görsel bağlantılarının önüne rastgele, tahmini zor karakterler eklenmesini sağlarsınız. Kolay erişimin önlenmesi için dizin indekslerinin kapalı olduğundan emin olun.', + 'app_editor' => 'Sayfa Düzenleyicisi', + 'app_editor_desc' => 'Sayfa düzenlemesi yapılırken, bütün kullanıcılar tarafından hangi düzenleyicinin kullanılacağını seçin.', + 'app_custom_html' => 'Özel HTML "Head" İçeriği', + 'app_custom_html_desc' => 'Buraya yazacağınız içerik, etiketinin içine ve en sonuna eklenecektir. Bu işlem, stil değişikliklerinin uygulanmasında ya da analytics kodlarının eklenmesinde yararlı olmaktadır.', + 'app_custom_html_disabled_notice' => 'Olası hatalı değişikliklerin geriye alınabilmesi için bu sayfanın özelleştirilmiş HTML "head" içeriği devre dışı bırakıldı.', 'app_logo' => 'Uygulama Logosu', - 'app_logo_desc' => 'Bu görsel 43px yüksekliğinde olmalı.
    Büyük görseller ölçeklenecektir.', + 'app_logo_desc' => 'Bu görsel 43px yüksekliğinde olmalıdır.
    Daha büyük görseller otomatik olarak küçültülecektir.', 'app_primary_color' => 'Uygulamanın Birincil Rengi', - 'app_primary_color_desc' => 'Bu bir hex değeri olmalıdır.
    Varsayılan rengi seçmek için boş bırakın.', - 'app_homepage' => 'Uygulama Anasayfası', - 'app_homepage_desc' => 'Anasayfada görünmesi için bir view seçin. Sayfa izinleri seçili sayfalar için yok sayılacaktır.', - 'app_homepage_select' => 'Sayfa seçiniz', - 'app_disable_comments' => 'Yorumları Engelle', - 'app_disable_comments_toggle' => 'Yorumları engelle', - 'app_disable_comments_desc' => 'Yorumları uygulamadaki bütün sayfalar için engelle.
    Mevcut yorumlar gösterilmeyecektir.', + 'app_primary_color_desc' => 'Başlık, butonlar ve bağlantılar da dahil olmak üzere uygulama için ana rengi ayarlar.', + 'app_homepage' => 'Ana Sayfa', + 'app_homepage_desc' => 'Varsayılan görünüm yerine ana sayfada görünmesi için bir görünüm seçin. Sayfa izinleri, burada seçeceğiniz sayfalar için yok sayılacaktır.', + 'app_homepage_select' => 'Bir sayfa seçin', + 'app_disable_comments' => 'Yorumları Devre Dışı Bırak', + 'app_disable_comments_toggle' => 'Yorumları devre dışı bırak', + 'app_disable_comments_desc' => 'Bütün sayfalar için yorumları devre dışı bırakır.
    Mevcut yorumlar gösterilmeyecektir.', // Color settings 'content_colors' => 'İçerik Renkleri', - 'content_colors_desc' => 'Sayfa organizasyon hiyerarşisi içerisindeki tüm elementler için renkleri ayarla. Renkleri benzer parlaklıkta seçmeniz okunurluk açısından önerilir.', + 'content_colors_desc' => 'Sayfa hiyerarşisinde bulunan bütün elemanlar için renkleri ayarlar. Bu renkleri varsayılan renklerin parlaklığına yakın bir parlaklıkta seçmeniz, okunurluğun iyileştirilmesi açısından önerilir.', 'bookshelf_color' => 'Raf Rengi', 'book_color' => 'Kitap Rengi', - 'chapter_color' => 'Kısım Rengi', + 'chapter_color' => 'Bölüm Rengi', 'page_color' => 'Sayfa Rengi', 'page_draft_color' => 'Sayfa Taslağı Rengi', // Registration Settings - 'reg_settings' => 'Kayıt', - 'reg_enable' => 'Kaydolmaya İzin Ver', - 'reg_enable_toggle' => 'Kaydolmaya izin ver', - 'reg_enable_desc' => 'Kayıt olmaya izin verdiğinizde kullanıcılar kendilerini uygulamaya kaydedebilecekler. Kayıt olduktan sonra kendilerine varsayılan kullanıcı rolü atanacaktır.', - 'reg_default_role' => 'Kayıt olduktan sonra varsayılan kullanıcı rolü', + 'reg_settings' => 'Kayıt İşlemleri', + 'reg_enable' => 'Kayıtları Aktifleştir', + 'reg_enable_toggle' => 'Kayıtları aktifleştir', + 'reg_enable_desc' => 'Kullanıcılar kaydolduktan sonra sizin belirleyeceğiniz bir role otomatik olarak atanabilirler.', + 'reg_default_role' => 'Kayıttan sonraki varsayılan kullanıcı rolü', 'reg_enable_external_warning' => 'Harici LDAP veya SAML kimlik doğrulaması etkinken yukarıdaki seçenek yok sayılır. Mevcut harici üyelere yönelik kimlik doğrulama başarılı olursa, mevcut olmayan üyelerin kullanıcı hesapları otomatik olarak oluşturulur.', - 'reg_email_confirmation' => 'Email Doğrulama', - 'reg_email_confirmation_toggle' => 'E-mail onayı gerektir', - 'reg_confirm_email_desc' => 'Eğer domain kısıtlaması kullanılıyorsa o zaman email doğrulaması gereklidir ve bu seçenek yok sayılacaktır.', - 'reg_confirm_restrict_domain' => 'Domain Kısıtlaması', - 'reg_confirm_restrict_domain_desc' => 'Kısıtlamak istediğiniz email domainlerini vigül ile ayırarak yazınız. Kullanıcılara uygulamaya erişmeden önce adreslerini doğrulamak için bir mail gönderilecektir.
    Kullanıcılar başarıyla kaydolduktan sonra email adreslerini değiştiremeyeceklerdir.', + 'reg_email_confirmation' => 'E-posta Doğrulaması', + 'reg_email_confirmation_toggle' => 'E-posta doğrulamasını zorunlu kıl', + 'reg_confirm_email_desc' => 'Eğer alan adı kısıtlaması kullanılıyorsa, bu seçenek yok sayılarak e-posta doğrulaması zorunlu kılınacaktır.', + 'reg_confirm_restrict_domain' => 'Alan Adı Kısıtlaması', + 'reg_confirm_restrict_domain_desc' => 'Kısıtlamak istediğiniz e-posta alan adlarını vigül ile ayırarak yazınız. Kullanıcılara, uygulamaya erişmeden önce adreslerini doğrulamaları için bir e-posta gönderilecektir.
    Başarılı bir kayıt işleminden sonra kullanıcıların e-posta adreslerini değiştirebileceklerini unutmayın.', 'reg_confirm_restrict_domain_placeholder' => 'Hiçbir kısıtlama tanımlanmamış', // Maintenance settings 'maint' => 'Bakım', - 'maint_image_cleanup' => 'Görsel Temizliği', - 'maint_image_cleanup_desc' => "Sayfaları ve revizyon içeriklerini tarayarak hangi gösel ve çizimlerin kullanımda olduğunu ve hangilerinin gereksiz olduğunu tespit eder. Bunu başlatmadan veritabanı ve görsellerin tam bir yedeğinin alındığından emin olun.", + 'maint_image_cleanup' => 'Görselleri Temizle', + 'maint_image_cleanup_desc' => "Sayfaları ve revizyon içeriklerini tarayarak hangi görsellerin ve çizimlerin kullanımda olduğunu ve hangilerinin gereksiz olduğunu tespit eder. Bunu başlatmadan önce veritabanının ve görsellerin tam bir yedeğinin alındığından emin olun.", 'maint_image_cleanup_ignore_revisions' => 'Revizyonlardaki görselleri yoksay', 'maint_image_cleanup_run' => 'Temizliği Başlat', - 'maint_image_cleanup_warning' => ':count potansiyel kullanılmayan görsel bulundu. Bu görselleri silmek istediğinizden emin misiniz?', - 'maint_image_cleanup_success' => ':count potanisyel kullanılmayan görsel bulundu ve silindi!', - 'maint_image_cleanup_nothing_found' => 'Kullanılmayan görsel bulunamadı ve birşey silinmedi!', - 'maint_send_test_email' => 'Test E-Postası Gönder', - 'maint_send_test_email_desc' => 'Bu profilinizde girdiğiniz e-posta adresine bir test e-postası gönderir.', - 'maint_send_test_email_run' => 'Test E-Postasını gönder', - 'maint_send_test_email_success' => 'E-Posta :address adresine gönderildi', - 'maint_send_test_email_mail_subject' => 'Test e-postası', - 'maint_send_test_email_mail_greeting' => 'E-Posta gönderimi başarılı!', + 'maint_image_cleanup_warning' => 'Muhtemelen kullanılmayan :count adet görsel bulundu. Bu görselleri silmek istediğinize emin misiniz?', + 'maint_image_cleanup_success' => 'Muhtemelen kullanılmayan :count adet görsel bulundu ve silindi!', + 'maint_image_cleanup_nothing_found' => 'Kullanılmayan görsel bulunamadığından hiçbir şey silinmedi!', + 'maint_send_test_email' => 'Deneme E-postası Gönder', + 'maint_send_test_email_desc' => 'Bu işlem, profilinize tanımladığınız e-posta adresine bir deneme e-postası gönderir.', + 'maint_send_test_email_run' => 'Deneme e-postasını gönder', + 'maint_send_test_email_success' => 'E-posta, :address adresine gönderildi', + 'maint_send_test_email_mail_subject' => 'Deneme E-postası', + 'maint_send_test_email_mail_greeting' => 'E-posta iletimi çalışıyor gibi görünüyor!', 'maint_send_test_email_mail_text' => 'Tebrikler! Eğer bu e-posta bildirimini alıyorsanız, e-posta ayarlarınız doğru bir şekilde ayarlanmış demektir.', // Role Settings 'roles' => 'Roller', 'role_user_roles' => 'Kullanıcı Rolleri', 'role_create' => 'Yeni Rol Oluştur', - 'role_create_success' => 'Rol Başarıyla Oluşturuldu', + 'role_create_success' => 'Rol, başarıyla oluşturuldu', 'role_delete' => 'Rolü Sil', - 'role_delete_confirm' => 'Bu işlem \':roleName\' rolünü silecektir.', - 'role_delete_users_assigned' => 'Bu role atanmış :userCount adet kullanıcı var. Eğer bu kullanıcıların rollerini değiştirmek istiyorsanız aşağıdan yeni bir rol seçin.', + 'role_delete_confirm' => 'Bu işlem, \':roleName\' adlı rolü silecektir.', + 'role_delete_users_assigned' => 'Bu role atanmış :userCount adet kullanıcı var. Eğer bu kullanıcıların rollerini değiştirmek istiyorsanız, aşağıdan yeni bir rol seçin.', 'role_delete_no_migration' => "Kullanıcıları taşıma", - 'role_delete_sure' => 'Bu rolü silmek istediğinizden emin misiniz?', + 'role_delete_sure' => 'Bu rolü silmek istediğinize emin misiniz?', 'role_delete_success' => 'Rol başarıyla silindi', 'role_edit' => 'Rolü Düzenle', 'role_details' => 'Rol Detayları', 'role_name' => 'Rol Adı', 'role_desc' => 'Rolün Kısa Tanımı', - 'role_external_auth_id' => 'Harici Authentication ID\'leri', + 'role_external_auth_id' => 'Harici Doğrulama Kimlikleri', 'role_system' => 'Sistem Yetkileri', 'role_manage_users' => 'Kullanıcıları yönet', 'role_manage_roles' => 'Rolleri ve rol izinlerini yönet', 'role_manage_entity_permissions' => 'Bütün kitap, bölüm ve sayfa izinlerini yönet', - 'role_manage_own_entity_permissions' => 'Sahip olunan kitap, bölüm ve sayfaların izinlerini yönet', + 'role_manage_own_entity_permissions' => 'Kendine ait kitabın, bölümün ve sayfaların izinlerini yönet', 'role_manage_page_templates' => 'Sayfa şablonlarını yönet', - 'role_access_api' => 'Sistem API\'na eriş', + 'role_access_api' => 'Sistem programlama arayüzüne (API) eriş', 'role_manage_settings' => 'Uygulama ayarlarını yönet', - 'role_asset' => 'Asset Yetkileri', - 'role_asset_desc' => 'Bu izinleri assetlere sistem içinden varsayılan erişimi kontrol eder. Kitaplar, bölümler ve sayfaların izinleri bu izinleri override eder.', - 'role_asset_admins' => 'Yöneticilere otomatik olarak bütün içeriğe erişim yetkisi verilir fakat bu opsiyonlar UI özelliklerini gösterir veya gizler.', + 'role_asset' => 'Varlık Yetkileri', + 'role_asset_desc' => 'Bu izinler, sistem içindeki varlıklara varsayılan erişim izinlerini ayarlar. Kitaplar, bölümler ve sayfalar üzerindeki izinler, buradaki izinleri geçersiz kılar.', + 'role_asset_admins' => 'Yöneticilere otomatik olarak bütün içeriğe erişim yetkisi verilir ancak bu seçenekler, kullanıcı arayüzündeki bazı seçeneklerin gösterilmesine veya gizlenmesine neden olabilir.', 'role_all' => 'Hepsi', - 'role_own' => 'Sahip Olunan', - 'role_controlled_by_asset' => 'Yükledikleri asset tarafından kontrol ediliyor', + 'role_own' => 'Kendine Ait', + 'role_controlled_by_asset' => 'Yüklendikleri varlık tarafından kontrol ediliyor', 'role_save' => 'Rolü Kaydet', 'role_update_success' => 'Rol başarıyla güncellendi', 'role_users' => 'Bu roldeki kullanıcılar', @@ -120,40 +120,40 @@ return [ 'users' => 'Kullanıcılar', 'user_profile' => 'Kullanıcı Profili', 'users_add_new' => 'Yeni Kullanıcı Ekle', - 'users_search' => 'Kullanıcıları Ara', + 'users_search' => 'Kullanıcı Ara', 'users_details' => 'Kullanıcı Detayları', - 'users_details_desc' => 'Bu kullanıcı için gösterilecek bir isim ve mail adresi belirleyin. Bu e-mail adresi kullanıcı tarafından giriş yaparken kullanılacak.', + 'users_details_desc' => 'Bu kullanıcı için gösterilecek bir isim ve e-posta adresi belirleyin. Buraya yazacağınız e-posta adresi, uygulamaya giriş yaparken kullanılacaktır.', 'users_details_desc_no_email' => 'Diğer kullanıcılar tarafından tanınabilmesi için bir isim belirleyin.', 'users_role' => 'Kullanıcı Rolleri', - 'users_role_desc' => 'Bu kullanıcının hangi rollere atanabileceğini belirleyin. Eğer bir kullanıcıya birden fazla rol atanırsa, kullanıcı bütün rollerin özelliklerini kullanabilir.', - 'users_password' => 'Kullanıcı Parolası', - 'users_password_desc' => 'Kullanıcının giriş yaparken kullanacağı bir parola belirleyin. Parola en az 5 karakter olmalıdır.', - 'users_send_invite_text' => 'Bu kullanıcıya parolasını sıfırlayabilmesi için bir e-posta gönder veya şifresini sen belirle.', - 'users_send_invite_option' => 'Kullanıcıya davet e-postası gönder', - 'users_external_auth_id' => 'Harici Authentication ID\'si', - 'users_external_auth_id_desc' => 'Bu ID, harici kimlik doğrulama sisteminizle iletişim kurarken bu kullanıcıyla eşleştirmek için kullanılır.', - 'users_password_warning' => 'Sadece parolanızı değiştirmek istiyorsanız aşağıyı doldurunuz.', - 'users_system_public' => 'Bu kullanıcı sizin uygulamanızı ziyaret eden bütün misafir kullanıcıları temsil eder. Giriş yapmak için kullanılamaz, otomatik olarak atanır.', - 'users_delete' => 'Kullanıcı Sil', + 'users_role_desc' => 'Bu kullanıcının hangi rollere atanacağını belirleyin. Birden fazla role sahip kullanıcılar, atandığı bütün rollerin yetkilerine sahip olurlar.', + 'users_password' => 'Kullanıcı Şifresi', + 'users_password_desc' => 'Kullanıcının giriş yaparken kullanacağı bir şifre belirleyin. Şifre en az 6 karakterden oluşmalıdır.', + 'users_send_invite_text' => 'Bu kullanıcıya kendi şifresini belirleyebilmesi için bir davetiye e-postası gönderebilir ya da kullanıcının şifresini kendiniz belirleyebilirsiniz.', + 'users_send_invite_option' => 'Kullanıcıya davetiye e-postası gönder', + 'users_external_auth_id' => 'Harici Doğrulama Kimliği', + 'users_external_auth_id_desc' => 'Bu kimlik numarası (ID), harici kimlik doğrulama sisteminizle iletişim kurarken bu kullanıcıyla eşleştirmek için kullanılır.', + 'users_password_warning' => 'Şifrenizi değiştirmek istiyorsanız, aşağıdaki formu doldurunuz.', + 'users_system_public' => 'Bu kullanıcı, uygulamanızı ziyaret eden bütün misafir kullanıcıları temsil eder. Giriş yapmak için kullanılamaz ancak otomatik olarak atanır.', + 'users_delete' => 'Kullanıcıyı Sil', 'users_delete_named' => ':userName kullanıcısını sil ', 'users_delete_warning' => 'Bu işlem \':userName\' kullanıcısını sistemden tamamen silecektir.', 'users_delete_confirm' => 'Bu kullanıcıyı tamamen silmek istediğinize emin misiniz?', 'users_delete_success' => 'Kullanıcılar başarıyla silindi.', - 'users_edit' => 'Kullanıcıyı Güncelle', + 'users_edit' => 'Kullanıcıyı Düzenle', 'users_edit_profile' => 'Profili Düzenle', 'users_edit_success' => 'Kullanıcı başarıyla güncellendi', - 'users_avatar' => 'Kullanıcı Avatarı', - 'users_avatar_desc' => 'Bu kullanıcıyı temsil eden bir görsel seçin. Yaklaşık 256px kare olmalıdır.', + 'users_avatar' => 'Avatar', + 'users_avatar_desc' => 'Bu kullanıcıyı temsil eden bir görsel seçin. Bu görsel yaklaşık 256px boyutunda bir kare olmalıdır.', 'users_preferred_language' => 'Tercih Edilen Dil', - 'users_preferred_language_desc' => 'Bu seçenek kullanıcı arayüzünün dilini değiştirecektir. Herhangi bir kullanıcı içeriğini etkilemeyecektir.', + 'users_preferred_language_desc' => 'Bu seçenek, kullanıcı arayüzünün dilini değiştirmek için kullanılır. Burada yapılan değişiklik herhangi bir kullanıcı tarafından oluşturulmuş içeriği etkilemeyecektir.', 'users_social_accounts' => 'Sosyal Hesaplar', - 'users_social_accounts_info' => 'Burada diğer hesaplarınızı ekleyerek daha hızlı ve kolay giriş sağlayabilirsiniz. Bir hesabın bağlantısını kesmek daha önce edilnilen erişiminizi kaldırmaz. Profil ayarlarınızdan bağlı sosyal hesabınızın erişimini kaldırınız.', - 'users_social_connect' => 'Hesap Bağla', + 'users_social_accounts_info' => 'Buraya diğer hesaplarınızı ekleyerek, uygulamaya daha hızlı ve kolay bir giriş sağlayabilirsiniz. Bir hesabın bağlantısını kesmek daha önce sahip olduğunuz erişimi kaldırmaz. Bağlı sosyal hesabınızın erişimini, profil ayarlarınızdan kaldırabilirsiniz.', + 'users_social_connect' => 'Hesabı Bağla', 'users_social_disconnect' => 'Hesabın Bağlantısını Kes', - 'users_social_connected' => ':socialAccount hesabı profilinize başarıyla bağlandı.', + 'users_social_connected' => ':socialAccount hesabı, profilinize başarıyla bağlandı.', 'users_social_disconnected' => ':socialAccount hesabınızın profilinizle ilişiği başarıyla kesildi.', 'users_api_tokens' => 'API Anahtarları', - 'users_api_tokens_none' => 'Bu kullanıcı için oluşturulmuş API anahtarı bulunmuyor', + 'users_api_tokens_none' => 'Bu kullanıcı için oluşturulmuş herhangi bir API anahtarı bulunamadı', 'users_api_tokens_create' => 'Anahtar Oluştur', 'users_api_tokens_expires' => 'Bitiş süresi', 'users_api_tokens_docs' => 'API Dokümantasyonu', @@ -164,20 +164,19 @@ return [ 'user_api_token_name_desc' => 'Anahtarınıza gelecekte ne amaçla kullanıldığını hatırlatması açısından anlamlı bir isim veriniz.', 'user_api_token_expiry' => 'Bitiş Tarihi', 'user_api_token_expiry_desc' => 'Bu anahtarın süresinin dolduğu bir tarih belirleyin. Bu tarihten sonra, bu anahtar kullanılarak yapılan istekler artık çalışmaz. Bu alanı boş bırakmak, bitiş tarihini 100 yıl sonrası yapar.', - 'user_api_token_create_secret_message' => 'Bu jetonu oluşturduktan hemen sonra bir "ID Anahtarı" "ve" Gizli Anahtar "oluşturulacak ve görüntülenecektir. -Gizli Anahtar yalnızca tek bir kez gösterilecektir, bu yüzden devam etmeden önce değeri güvenli bir yere kopyaladığınızdan emin olun.', + 'user_api_token_create_secret_message' => 'Bu anahtar oluşturulduktan hemen sonra bir "ID Anahtarı" ve "Gizli Anahtar" üretilip görüntülenecektir. Gizli anahtar sadece bir defa gösterilecektir, bu yüzden devam etmeden önce bu değeri güvenli bir yere kopyaladığınızdan emin olun.', 'user_api_token_create_success' => 'API anahtarı başarıyla oluşturuldu', 'user_api_token_update_success' => 'API anahtarı başarıyla güncellendi', 'user_api_token' => 'API Erişim Anahtarı', 'user_api_token_id' => 'Anahtar ID', - 'user_api_token_id_desc' => 'Bu API isteklerini karşılamak için sistem tarafından oluşturulmuş sonradan düzenlenemez bir tanımlayıcıdır.', + 'user_api_token_id_desc' => 'Bu, API isteklerini karşılamak için sistem tarafından oluşturulmuş ve sonradan düzenlenemeyen bir tanımlayıcıdır.', 'user_api_token_secret' => 'Gizli Anahtar', - 'user_api_token_secret_desc' => 'Bu, API isteklerinde sağlanması gereken anahtar için sistem tarafından oluşturulan bir gizli anahtardır. Bu yalnızca bir kez görüntülenecektir, bu nedenle bu değeri güvenli bir yere kopyalayın.', - 'user_api_token_created' => 'Anahtar :timeAgo Önce Oluşturuldu', - 'user_api_token_updated' => 'Anahtar :timeAgo Önce Güncellendi', + 'user_api_token_secret_desc' => 'Bu, API isteklerinde sağlanması gereken anahtar için sistem tarafından oluşturulan bir gizli anahtardır. Bu anahtar sadece bir defa görüntülenecektir, bu nedenle bu değeri güvenli bir yere kopyalayın.', + 'user_api_token_created' => 'Anahtar :timeAgo Oluşturuldu', + 'user_api_token_updated' => 'Anahtar :timeAgo Güncellendi', 'user_api_token_delete' => 'Anahtarı Sil', 'user_api_token_delete_warning' => 'Bu işlem \':tokenName\' adındaki API anahtarını sistemden tamamen silecektir.', - 'user_api_token_delete_confirm' => 'Bu API anahtarını silmek istediğinizden emin misiniz?', + 'user_api_token_delete_confirm' => 'Bu API anahtarını silmek istediğinize emin misiniz?', 'user_api_token_delete_success' => 'API anahtarı başarıyla silindi', //! If editing translations files directly please ignore this in all @@ -193,6 +192,7 @@ Gizli Anahtar yalnızca tek bir kez gösterilecektir, bu yüzden devam etmeden 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'İbranice', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/tr/validation.php b/resources/lang/tr/validation.php index 18328ce75..801ec89da 100644 --- a/resources/lang/tr/validation.php +++ b/resources/lang/tr/validation.php @@ -9,103 +9,103 @@ return [ // Standard laravel validation lines 'accepted' => ':attribute kabul edilmelidir.', - 'active_url' => ':attribute geçerli bir URL adresi değildir.', - 'after' => ':attribute :date tarihinden sonra bir tarih olmalıdır.', + 'active_url' => ':attribute, geçerli bir URL adresi değildir.', + 'after' => ':attribute tarihi, :date tarihinden sonraki bir tarih olmalıdır.', 'alpha' => ':attribute sadece harflerden oluşabilir.', 'alpha_dash' => ':attribute sadece harf, rakam ve tirelerden oluşabilir.', - 'alpha_num' => ':attribute sadece harf ve rakam oluşabilir.', - 'array' => ':attribute array olmalıdır..', - 'before' => ':attribute :date tarihinden önce bir tarih olmalıdır.', + 'alpha_num' => ':attribute sadece harflerden ve rakamlardan oluşabilir.', + 'array' => ':attribute bir dizi olmalıdır.', + 'before' => ':attribute tarihi, :date tarihinden önceki bir tarih olmalıdır.', 'between' => [ - 'numeric' => ':attribute, :min ve :max değerleri arasında olmalıdır.', + 'numeric' => ':attribute değeri, :min ve :max değerleri arasında olmalıdır.', 'file' => ':attribute, :min ve :max kilobyte boyutları arasında olmalıdır.', 'string' => ':attribute, :min ve :max karakter arasında olmalıdır.', - 'array' => ':attribute :min ve :max öge arasında olmalıdır.', + 'array' => ':attribute, :min ve :max öge arasında olmalıdır.', ], - 'boolean' => ':attribute true veya false olmalıdır.', + 'boolean' => ':attribute değeri true veya false olmalıdır.', 'confirmed' => ':attribute doğrulaması eşleşmiyor.', 'date' => ':attribute geçerli bir tarih değil.', - 'date_format' => ':attribute formatı :format\'ına uymuyor.', - 'different' => ':attribute be :other birbirinden farklı olmalıdır.', - 'digits' => ':attribute :digits basamaklı olmalıdır.', - 'digits_between' => ':attribute :min ve :max basamaklı olmalıdır.', - 'email' => ':attribute geçerli bir e-mail adresi olmalıdır.', - 'ends_with' => ':attribute şunlardan biriyle bitmelidir: :values', - 'filled' => ':attribute gerekli bir alandır.', + 'date_format' => ':attribute formatı, :format formatına uymuyor.', + 'different' => ':attribute ve :other birbirinden farklı olmalıdır.', + 'digits' => ':attribute, :digits basamaklı olmalıdır.', + 'digits_between' => ':attribute, en az :min ve en fazla :max basamaklı olmalıdır.', + 'email' => ':attribute, geçerli bir e-posta adresi olmalıdır.', + 'ends_with' => ':attribute, şunlardan birisiyle bitmelidir: :values', + 'filled' => ':attribute alanı zorunludur.', 'gt' => [ - 'numeric' => ':attribute :max değerinden büyük olmalı.', - 'file' => ':attribute değeri :value kilobayt değerinden büyük olmalıdır.', - 'string' => ':attribute değeri :value karakter değerinden büyük olmalıdır.', - 'array' => ':attribute, :value öğeden daha fazlasına sahip olamaz.', + 'numeric' => ':attribute, :max değerinden büyük olmalıdır.', + 'file' => ':attribute, :value kilobayttan büyük olmalıdır.', + 'string' => ':attribute, :value karakterden fazla olmalıdır.', + 'array' => ':attribute, :value ögeden daha fazla öge içermelidir.', ], 'gte' => [ - 'numeric' => ':attribute, :value değerinden büyük veya eşit olmalı.', - 'file' => ':attribute, :value kilobayttan eşit ya da büyük olmalı.', - 'string' => ':attribute, :value kilobayttan eşit ya da büyük olmalı.', - 'array' => ':attribute, :value veya daha fazla maddeye sahip olmalıdır.', + 'numeric' => ':attribute, :value değerinden büyük veya bu değere eşit olmalıdır.', + 'file' => ':attribute, en az :value kilobayt olmalıdır.', + 'string' => ':attribute, en az :value karakter içermelidir.', + 'array' => ':attribute, en az :value öge içermelidir.', ], - 'exists' => 'Seçilen :attribute geçerli bir alan değildir.', - 'image' => ':attribute bir görsel olmalıdır.', - 'image_extension' => ':attribute geçerli ve desteklenen bir görsel uzantısı değildir.', - 'in' => 'Seçilen :attribute geçerli değildir.', - 'integer' => ':attribute bir integer değeri olmalıdır.', - 'ip' => ':attribute geçerli bir IP adresi olmalıdır.', - 'ipv4' => ': Özniteliği geçerli bir IPv4 adresi olmalıdır.', - 'ipv6' => ':attribute geçerli bir IPv6 adresi olmalıdır.', - 'json' => ':attribute geçerli bir JSON dizini olmalı.', + 'exists' => 'Seçilen :attribute geçersiz.', + 'image' => ':attribute, bir görsel olmalıdır.', + 'image_extension' => ':attribute, geçerli ve desteklenen bir görsel uzantısına sahip olmalıdır.', + 'in' => 'Seçilen :attribute geçersizdir.', + 'integer' => ':attribute, bir tam sayı olmalıdır.', + 'ip' => ':attribute, geçerli bir IP adresi olmalıdır.', + 'ipv4' => ':attribute, geçerli bir IPv4 adresi olmalıdır.', + 'ipv6' => ':attribute, geçerli bir IPv6 adresi olmalıdır.', + 'json' => ':attribute, geçerli bir JSON dizimi olmalıdır.', 'lt' => [ 'numeric' => ':attribute, :value değerinden küçük olmalıdır.', - 'file' => ':attribute, :value kilobayt boyutundan küçük olmalıdır.', + 'file' => ':attribute, :value kilobayttan küçük olmalıdır.', 'string' => ':attribute, :value karakterden küçük olmalıdır.', - 'array' => ':attribute, :value öğeden az olmalıdır.', + 'array' => ':attribute, :value ögeden az olmalıdır.', ], 'lte' => [ - 'numeric' => ':attribute, :value değerinden küçük veya eşit olmalıdır.', - 'file' => ':attribute, :value kilobayttan küçük ya da eşit olmalıdır.', - 'string' => ':attribute, :value kilobayttan küçük ya da eşit olmalıdır.', - 'array' => ':attribute, :value öğeden daha fazlasına sahip olamaz.', + 'numeric' => ':attribute, en fazla :value değerine eşit olmalıdır.', + 'file' => ':attribute, en fazla :value kilobayt olmalıdır.', + 'string' => ':attribute, en fazla :value karakter içermelidir.', + 'array' => ':attribute, en fazla :value öge içermelidir.', ], 'max' => [ - 'numeric' => ':attribute, :max değerinden büyük olmamalıdır.', - 'file' => ':attribute, :max kilobyte boyutundan büyük olmamalıdır.', - 'string' => ':attribute, :max karakter boyutundan büyük olmamalıdır.', - 'array' => ':attribute, en fazla :max öge içermelidir.', + 'numeric' => ':attribute, :max değerinden büyük olmayabilir.', + 'file' => ':attribute, :max kilobayttan büyük olmayabilir.', + 'string' => ':attribute, :max karakterden daha fazla karakter içermiyor olabilir.', + 'array' => ':attribute, :max ögeden daha fazla öge içermiyor olabilir.', ], - 'mimes' => ':attribute :values dosya tipinde olmalıdır.', + 'mimes' => ':attribute, şu dosya tiplerinde olmalıdır: :values.', 'min' => [ 'numeric' => ':attribute, :min değerinden az olmamalıdır.', - 'file' => ':attribute, :min kilobyte boyutundan küçük olmamalıdır.', - 'string' => ':attribute, :min karakter boyutundan küçük olmamalıdır.', + 'file' => ':attribute, :min kilobayttan küçük olmamalıdır.', + 'string' => ':attribute, en az :min karakter içermelidir.', 'array' => ':attribute, en az :min öge içermelidir.', ], - 'no_double_extension' => ':attribute sadece tek bir dosya tipinde olmalıdır.', - 'not_in' => 'Seçili :attribute geçerli değildir.', - 'not_regex' => ':attribute formatı geçerli değildir.', - 'numeric' => ':attribute rakam olmalıdır.', - 'regex' => ':attribute formatı geçerli değildir.', - 'required' => 'The :attribute field is required. :attribute alanı gereklidir.', - 'required_if' => ':other alanı :value değerinde ise :attribute alanı gereklidir.', - 'required_with' => 'Eğer :values değeri geçerli ise :attribute alanı gereklidir.', - 'required_with_all' => 'Eğer :values değeri geçerli ise :attribute alanı gereklidir. ', - 'required_without' => 'Eğer :values değeri geçerli değil ise :attribute alanı gereklidir.', - 'required_without_all' => 'Eğer :values değerlerinden hiçbiri geçerli değil ise :attribute alanı gereklidir.', + 'no_double_extension' => ':attribute, sadece tek bir dosya tipinde olmalıdır.', + 'not_in' => 'Seçili :attribute geçersiz.', + 'not_regex' => ':attribute formatı geçersiz.', + 'numeric' => ':attribute, bir sayı olmalıdır.', + 'regex' => ':attribute formatı geçersiz.', + 'required' => ':attribute alanı zorunludur.', + 'required_if' => ':other alanının :value olması, :attribute alanını zorunlu kılar.', + 'required_with' => ':values değerinin mevcudiyeti, :attribute alanını zorunlu kılar.', + 'required_with_all' => ':values değerlerinin mevcudiyeti, :attribute alanını zorunlu kılar.', + 'required_without' => ':values değerinin bulunmuyor olması, :attribute alanını zorunlu kılar.', + 'required_without_all' => ':values değerlerinden hiçbirinin bulunmuyor olması, :attribute alanını zorunlu kılar.', 'same' => ':attribute ve :other eşleşmelidir.', 'size' => [ 'numeric' => ':attribute, :size boyutunda olmalıdır.', - 'file' => ':attribute, :size kilobyte boyutunda olmalıdır.', + 'file' => ':attribute, :size kilobayt olmalıdır.', 'string' => ':attribute, :size karakter uzunluğunda olmalıdır.', 'array' => ':attribute, :size sayıda öge içermelidir.', ], - 'string' => ':attribute string olmalıdır.', - 'timezone' => ':attribute geçerli bir alan olmalıdır.', - 'unique' => ':attribute daha önce alınmış.', - 'url' => ':attribute formatı geçerli değil.', - 'uploaded' => 'Dosya yüklemesi başarısız oldu. Server bu boyutta dosyaları kabul etmiyor olabilir.', + 'string' => ':attribute, string olmalıdır.', + 'timezone' => ':attribute, geçerli bir bölge olmalıdır.', + 'unique' => ':attribute zaten alınmış.', + 'url' => ':attribute formatı geçersiz.', + 'uploaded' => 'Dosya yüklemesi başarısız oldu. Sunucu, bu boyuttaki dosyaları kabul etmiyor olabilir.', // Custom validation lines 'custom' => [ 'password-confirm' => [ - 'required_with' => 'Parola onayı gereklidir.', + 'required_with' => 'Şifre onayı zorunludur', ], ], diff --git a/resources/lang/uk/auth.php b/resources/lang/uk/auth.php index b8fcc06ad..3b6e354c4 100644 --- a/resources/lang/uk/auth.php +++ b/resources/lang/uk/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Скинути пароль', 'reset_password_send_instructions' => 'Введіть адресу електронної пошти нижче, і вам буде надіслано електронне повідомлення з посиланням на зміну пароля.', 'reset_password_send_button' => 'Надіслати посилання для скидання пароля', - 'reset_password_sent_success' => 'Посилання для скидання пароля було надіслано на :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Ваш пароль успішно скинуто.', 'email_reset_subject' => 'Скинути ваш пароль :appName', 'email_reset_text' => 'Ви отримали цей електронний лист, оскільки до нас надійшов запит на скидання пароля для вашого облікового запису.', diff --git a/resources/lang/uk/common.php b/resources/lang/uk/common.php index 214fbcb4e..225429ffa 100644 --- a/resources/lang/uk/common.php +++ b/resources/lang/uk/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Меню профілю', 'view_profile' => 'Переглянути профіль', 'edit_profile' => 'Редагувати профіль', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Інфо', diff --git a/resources/lang/uk/passwords.php b/resources/lang/uk/passwords.php index 1a0cd0341..250bec3fb 100644 --- a/resources/lang/uk/passwords.php +++ b/resources/lang/uk/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Пароль повинен містити не менше восьми символів і збігатись з підтвердженням.', 'user' => "Ми не можемо знайти користувача з цією адресою електронної пошти.", - 'token' => 'Цей токен для скидання пароля недійсний.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'Ми надіслали Вам електронний лист із посиланням для скидання пароля!', 'reset' => 'Ваш пароль скинуто!', diff --git a/resources/lang/uk/settings.php b/resources/lang/uk/settings.php index daf8a56d5..d7dd8397b 100644 --- a/resources/lang/uk/settings.php +++ b/resources/lang/uk/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/vi/auth.php b/resources/lang/vi/auth.php index ef8c6335f..bd13572cb 100644 --- a/resources/lang/vi/auth.php +++ b/resources/lang/vi/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Đặt lại mật khẩu', 'reset_password_send_instructions' => 'Nhập email vào ô dưới đây và bạn sẽ nhận được một email với liên kết để đặt lại mật khẩu.', 'reset_password_send_button' => 'Gửi liên kết đặt lại mật khẩu', - 'reset_password_sent_success' => 'Một liên kết đặt lại mật khẩu đã được gửi tới :email.', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => 'Mật khẩu đã được đặt lại thành công.', 'email_reset_subject' => 'Đặt lại mật khẩu của :appName', 'email_reset_text' => 'Bạn nhận được email này bởi vì chúng tôi nhận được một yêu cầu đặt lại mật khẩu cho tài khoản của bạn.', diff --git a/resources/lang/vi/common.php b/resources/lang/vi/common.php index 777fb5776..2b56b4639 100644 --- a/resources/lang/vi/common.php +++ b/resources/lang/vi/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Menu Hồ sơ', 'view_profile' => 'Xem Hồ sơ', 'edit_profile' => 'Sửa Hồ sơ', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Thông tin', diff --git a/resources/lang/vi/passwords.php b/resources/lang/vi/passwords.php index d97296158..21242e003 100644 --- a/resources/lang/vi/passwords.php +++ b/resources/lang/vi/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Mật khẩu phải có tối thiểu 8 ký tự và và phải trùng với mật khẩu xác nhận.', 'user' => "Chúng tôi không tìm thấy người dùng với địa chỉ email đó.", - 'token' => 'Token đặt lại mật khẩu không hợp lệ.', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'Chúng tôi đã gửi email chứa liên kết đặt lại mật khẩu cho bạn!', 'reset' => 'Mật khẩu của bạn đã được đặt lại!', diff --git a/resources/lang/vi/settings.php b/resources/lang/vi/settings.php index 8886acd7b..4f7469228 100644 --- a/resources/lang/vi/settings.php +++ b/resources/lang/vi/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/zh_CN/auth.php b/resources/lang/zh_CN/auth.php index 0eec01508..e1d25078d 100644 --- a/resources/lang/zh_CN/auth.php +++ b/resources/lang/zh_CN/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => '重置密码', 'reset_password_send_instructions' => '在下面输入您的Email地址,您将收到一封带有密码重置链接的邮件。', 'reset_password_send_button' => '发送重置链接', - 'reset_password_sent_success' => '密码重置链接已发送到:email。', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => '您的密码已成功重置。', 'email_reset_subject' => '重置您的:appName密码', 'email_reset_text' => '您收到此电子邮件是因为我们收到了您的帐户的密码重置请求。', diff --git a/resources/lang/zh_CN/common.php b/resources/lang/zh_CN/common.php index c21e8029d..bc9e94d18 100644 --- a/resources/lang/zh_CN/common.php +++ b/resources/lang/zh_CN/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => '个人资料', 'view_profile' => '查看资料', 'edit_profile' => '编辑资料', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => '信息', diff --git a/resources/lang/zh_CN/passwords.php b/resources/lang/zh_CN/passwords.php index afdad8423..ac3f5e2ae 100644 --- a/resources/lang/zh_CN/passwords.php +++ b/resources/lang/zh_CN/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => '密码必须至少包含六个字符并与确认相符。', 'user' => "使用该Email地址的用户不存在。", - 'token' => '此密码重置令牌无效。', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => '我们已经通过Email发送您的密码重置链接!', 'reset' => '您的密码已被重置!', diff --git a/resources/lang/zh_CN/settings.php b/resources/lang/zh_CN/settings.php index b7dded317..1c2a0aa18 100755 --- a/resources/lang/zh_CN/settings.php +++ b/resources/lang/zh_CN/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', diff --git a/resources/lang/zh_TW/auth.php b/resources/lang/zh_TW/auth.php index 6b1f75f75..c72e5d206 100644 --- a/resources/lang/zh_TW/auth.php +++ b/resources/lang/zh_TW/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => '重置密碼', 'reset_password_send_instructions' => '在下方輸入您的Email位址,您將收到一封帶有密碼重置連結的郵件。', 'reset_password_send_button' => '發送重置連結', - 'reset_password_sent_success' => '密碼重置連結已發送到:email。', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', 'reset_password_success' => '您的密碼已成功重置。', 'email_reset_subject' => '重置您的:appName密碼', 'email_reset_text' => '您收到此電子郵件是因為我們收到了您的帳號的密碼重置請求。', diff --git a/resources/lang/zh_TW/common.php b/resources/lang/zh_TW/common.php index d82945ac0..c86b0940c 100644 --- a/resources/lang/zh_TW/common.php +++ b/resources/lang/zh_TW/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => '個人資料菜單', 'view_profile' => '檢視資料', 'edit_profile' => '編輯資料', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => '訊息', diff --git a/resources/lang/zh_TW/passwords.php b/resources/lang/zh_TW/passwords.php index d1f0aeb08..7d93b302b 100644 --- a/resources/lang/zh_TW/passwords.php +++ b/resources/lang/zh_TW/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => '密碼必須至少包含六個字元並與確認相符。', 'user' => "使用該Email位址的使用者不存在。", - 'token' => '此密碼重置 Session 無效。', + 'token' => 'The password reset token is invalid for this email address.', 'sent' => '我們已經透過Email發送您的密碼重置連結。', 'reset' => '您的密碼已被重置。', diff --git a/resources/lang/zh_TW/settings.php b/resources/lang/zh_TW/settings.php index 02c11e5de..f43e4204f 100644 --- a/resources/lang/zh_TW/settings.php +++ b/resources/lang/zh_TW/settings.php @@ -192,6 +192,7 @@ return [ 'es' => 'Español', 'es_AR' => 'Español Argentina', 'fr' => 'Français', + 'he' => 'עברית', 'hu' => 'Magyar', 'it' => 'Italian', 'ja' => '日本語', From d030620846cffcad0e512a36f8e348de329b1717 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 13 Apr 2020 15:43:20 +0100 Subject: [PATCH 035/197] Updated translator contributor file from crowdin --- .github/translators.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/translators.txt b/.github/translators.txt index 23807a00b..ca8f0e218 100644 --- a/.github/translators.txt +++ b/.github/translators.txt @@ -87,3 +87,11 @@ Rafael (raribeir) :: Portuguese, Brazilian Hiroyuki Odake (dakesan) :: Japanese Alex Lee (qianmengnet) :: Chinese Simplified swinn37 :: French +Hasan Özbey (the-turk) :: Turkish +rcy :: Swedish +Ali Yasir Yılmaz (ayyilmaz) :: Turkish +scureza :: Italian +Biepa :: German Informal; German +syecu :: Chinese Simplified +Lap1t0r :: French +Thinkverse (thinkverse) :: Swedish From 79a949836b93c89b5efd9d9cf94e0f2b93dda48f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 25 Apr 2020 16:38:11 +0100 Subject: [PATCH 036/197] Fixed incorrect API listing total when offset set Fixes #2043 --- app/Api/ListingResponseBuilder.php | 2 +- tests/Api/ApiListingTest.php | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/Api/ListingResponseBuilder.php b/app/Api/ListingResponseBuilder.php index 2fa5644c3..942c5d270 100644 --- a/app/Api/ListingResponseBuilder.php +++ b/app/Api/ListingResponseBuilder.php @@ -36,8 +36,8 @@ class ListingResponseBuilder */ public function toResponse() { - $data = $this->fetchData(); $total = $this->query->count(); + $data = $this->fetchData(); return response()->json([ 'data' => $data, diff --git a/tests/Api/ApiListingTest.php b/tests/Api/ApiListingTest.php index ac6d61aa1..bb4920cc3 100644 --- a/tests/Api/ApiListingTest.php +++ b/tests/Api/ApiListingTest.php @@ -81,4 +81,20 @@ class ApiListingTest extends TestCase } } + public function test_total_on_results_shows_correctly() + { + $this->actingAsApiEditor(); + $bookCount = Book::query()->count(); + $resp = $this->get($this->endpoint . '?count=1'); + $resp->assertJson(['total' => $bookCount ]); + } + + public function test_total_on_results_shows_correctly_when_offset_provided() + { + $this->actingAsApiEditor(); + $bookCount = Book::query()->count(); + $resp = $this->get($this->endpoint . '?count=1&offset=1'); + $resp->assertJson(['total' => $bookCount ]); + } + } \ No newline at end of file From 519283e643f9697952d49c7009dd9e9745cb4319 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 25 Apr 2020 18:19:22 +0100 Subject: [PATCH 037/197] Authenticated admins on all guards upon login For #2031 --- app/Http/Controllers/Auth/LoginController.php | 20 +++++++++++++++ tests/Auth/AuthTest.php | 25 ++++++++++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 4660c16d5..fb2573b5c 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -125,6 +125,26 @@ class LoginController extends Controller return $this->sendFailedLoginResponse($request); } + /** + * The user has been authenticated. + * + * @param \Illuminate\Http\Request $request + * @param mixed $user + * @return mixed + */ + protected function authenticated(Request $request, $user) + { + // Authenticate on all session guards if a likely admin + if ($user->can('users-manage') && $user->can('user-roles-manage')) { + $guards = ['standard', 'ldap', 'saml2']; + foreach ($guards as $guard) { + auth($guard)->login($user); + } + } + + return redirect()->intended($this->redirectPath()); + } + /** * Validate the user login request. * diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php index 40bcda713..f1f476966 100644 --- a/tests/Auth/AuthTest.php +++ b/tests/Auth/AuthTest.php @@ -381,13 +381,30 @@ class AuthTest extends BrowserKitTest ->seePageUrlIs($page->getUrl()); } + public function test_login_authenticates_admins_on_all_guards() + { + $this->post('/login', ['email' => 'admin@admin.com', 'password' => 'password']); + $this->assertTrue(auth()->check()); + $this->assertTrue(auth('ldap')->check()); + $this->assertTrue(auth('saml2')->check()); + } + + public function test_login_authenticates_nonadmins_on_default_guard_only() + { + $editor = $this->getEditor(); + $editor->password = bcrypt('password'); + $editor->save(); + + $this->post('/login', ['email' => $editor->email, 'password' => 'password']); + $this->assertTrue(auth()->check()); + $this->assertFalse(auth('ldap')->check()); + $this->assertFalse(auth('saml2')->check()); + } + /** * Perform a login - * @param string $email - * @param string $password - * @return $this */ - protected function login($email, $password) + protected function login(string $email, string $password): AuthTest { return $this->visit('/login') ->type($email, '#email') From 07831df2d34249fa9ccb53579520e12137475b7e Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 25 Apr 2020 18:28:07 +0100 Subject: [PATCH 038/197] Updated user-create endpoint so saml and ldap is consistent. --- app/Http/Controllers/UserController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 775e2a984..97ec31dcc 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -76,7 +76,7 @@ class UserController extends Controller if ($authMethod === 'standard' && !$sendInvite) { $validationRules['password'] = 'required|min:6'; $validationRules['password-confirm'] = 'required|same:password'; - } elseif ($authMethod === 'ldap') { + } elseif ($authMethod === 'ldap' || $authMethod === 'saml2') { $validationRules['external_auth_id'] = 'required'; } $this->validate($request, $validationRules); @@ -85,7 +85,7 @@ class UserController extends Controller if ($authMethod === 'standard') { $user->password = bcrypt($request->get('password', Str::random(32))); - } elseif ($authMethod === 'ldap') { + } elseif ($authMethod === 'ldap' || $authMethod === 'saml2') { $user->external_auth_id = $request->get('external_auth_id'); } From a880b1d5c55ae3fb2a5cb7414448097f22e1c643 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 25 Apr 2020 19:19:41 +0100 Subject: [PATCH 039/197] Fixed selection not visible - dark theme codemirror Fixes #2060 --- resources/sass/_codemirror.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/sass/_codemirror.scss b/resources/sass/_codemirror.scss index c679e4899..f65a7c422 100644 --- a/resources/sass/_codemirror.scss +++ b/resources/sass/_codemirror.scss @@ -459,7 +459,10 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} height: auto; margin-bottom: $-l; border: 1px solid; - @include lightDark(border-color, #DDD, #111) + @include lightDark(border-color, #DDD, #111); +} +html.dark-mode .CodeMirror pre { + background-color: transparent; } .cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 0; color: #333; } From c20110b6aee27992e0092b2933409ee572fe811c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 25 Apr 2020 19:55:16 +0100 Subject: [PATCH 040/197] Fixed issue where callout and quotes overlap floated images For #2055 --- resources/sass/_blocks.scss | 1 + resources/sass/_text.scss | 1 + 2 files changed, 2 insertions(+) diff --git a/resources/sass/_blocks.scss b/resources/sass/_blocks.scss index 173dd3baa..b6f35376d 100644 --- a/resources/sass/_blocks.scss +++ b/resources/sass/_blocks.scss @@ -8,6 +8,7 @@ padding: $-s $-s $-s $-xl; display: block; position: relative; + overflow: auto; &:before { background-image: url('data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9IiMwMTUzODAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+ICAgIDxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz4gICAgPHBhdGggZD0iTTEyIDJDNi40OCAyIDIgNi40OCAyIDEyczQuNDggMTAgMTAgMTAgMTAtNC40OCAxMC0xMFMxNy41MiAyIDEyIDJ6bTEgMTVoLTJ2LTZoMnY2em0wLThoLTJWN2gydjJ6Ii8+PC9zdmc+'); background-repeat: no-repeat; diff --git a/resources/sass/_text.scss b/resources/sass/_text.scss index 3455a3ac4..a2a5281d9 100644 --- a/resources/sass/_text.scss +++ b/resources/sass/_text.scss @@ -206,6 +206,7 @@ blockquote { border-left: 4px solid var(--color-primary); @include lightDark(background-color, #f8f8f8, #333); padding: $-s $-m $-s $-xl; + overflow: auto; &:before { content: "\201C"; font-size: 2em; From 8fb1f7c3617de91784fa0ca3054d8f9e9d283a34 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 25 Apr 2020 19:59:23 +0100 Subject: [PATCH 041/197] Fixed floated content extending past page body As shown in #2055 --- resources/sass/_layout.scss | 6 +++--- resources/views/pages/show.blade.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/sass/_layout.scss b/resources/sass/_layout.scss index 197d5271b..595713feb 100644 --- a/resources/sass/_layout.scss +++ b/resources/sass/_layout.scss @@ -184,12 +184,12 @@ body.flexbox { /** * Fixes */ -.clearfix:before, -.clearfix:after { +.clearfix::before, +.clearfix::after { content: " "; display: table; } -.clearfix:after { +.clearfix::after { clear: both; } diff --git a/resources/views/pages/show.blade.php b/resources/views/pages/show.blade.php index dfe0a9d7d..cfa5ee9ce 100644 --- a/resources/views/pages/show.blade.php +++ b/resources/views/pages/show.blade.php @@ -11,7 +11,7 @@
    -
    +
    @include('pages.pointer', ['page' => $page]) @include('pages.page-display')
    From a17b82bdde2d1b61d6780ef0c33d071bbf0daba6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 25 Apr 2020 21:37:52 +0100 Subject: [PATCH 042/197] Fixed api query total not taking filters into account --- app/Api/ListingResponseBuilder.php | 3 ++- app/Config/snappy.php | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/Api/ListingResponseBuilder.php b/app/Api/ListingResponseBuilder.php index 942c5d270..5245a5d90 100644 --- a/app/Api/ListingResponseBuilder.php +++ b/app/Api/ListingResponseBuilder.php @@ -36,6 +36,8 @@ class ListingResponseBuilder */ public function toResponse() { + $this->applyFiltering($this->query); + $total = $this->query->count(); $data = $this->fetchData(); @@ -52,7 +54,6 @@ class ListingResponseBuilder { $this->applyCountAndOffset($this->query); $this->applySorting($this->query); - $this->applyFiltering($this->query); return $this->query->get($this->fields); } diff --git a/app/Config/snappy.php b/app/Config/snappy.php index 60c26ffd5..f347eda23 100644 --- a/app/Config/snappy.php +++ b/app/Config/snappy.php @@ -13,7 +13,9 @@ return [ 'enabled' => true, 'binary' => file_exists(base_path('wkhtmltopdf')) ? base_path('wkhtmltopdf') : env('WKHTMLTOPDF', false), 'timeout' => false, - 'options' => [], + 'options' => [ + 'outline' => true + ], 'env' => [], ], 'image' => [ From 2ec4ad118177fa1cacf0dc2f834ef3c0ad3102e0 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 25 Apr 2020 22:15:59 +0100 Subject: [PATCH 043/197] Tweaked ListingResponseBuilder to help avoid future issues - Updated so none of the method mutate the query throughout the function so that the query can be handled in a sane way, Since we were already encountering issues due to internal method call order. --- app/Api/ListingResponseBuilder.php | 32 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/app/Api/ListingResponseBuilder.php b/app/Api/ListingResponseBuilder.php index 5245a5d90..df4cb8bf1 100644 --- a/app/Api/ListingResponseBuilder.php +++ b/app/Api/ListingResponseBuilder.php @@ -36,10 +36,10 @@ class ListingResponseBuilder */ public function toResponse() { - $this->applyFiltering($this->query); + $filteredQuery = $this->filterQuery($this->query); - $total = $this->query->count(); - $data = $this->fetchData(); + $total = $filteredQuery->count(); + $data = $this->fetchData($filteredQuery); return response()->json([ 'data' => $data, @@ -50,22 +50,22 @@ class ListingResponseBuilder /** * Fetch the data to return in the response. */ - protected function fetchData(): Collection + protected function fetchData(Builder $query): Collection { - $this->applyCountAndOffset($this->query); - $this->applySorting($this->query); - - return $this->query->get($this->fields); + $query = $this->countAndOffsetQuery($query); + $query = $this->sortQuery($query); + return $query->get($this->fields); } /** * Apply any filtering operations found in the request. */ - protected function applyFiltering(Builder $query) + protected function filterQuery(Builder $query): Builder { + $query = clone $query; $requestFilters = $this->request->get('filter', []); if (!is_array($requestFilters)) { - return; + return $query; } $queryFilters = collect($requestFilters)->map(function ($value, $key) { @@ -74,7 +74,7 @@ class ListingResponseBuilder return !is_null($value); })->values()->toArray(); - $query->where($queryFilters); + return $query->where($queryFilters); } /** @@ -102,8 +102,9 @@ class ListingResponseBuilder * Apply sorting operations to the query from given parameters * otherwise falling back to the first given field, ascending. */ - protected function applySorting(Builder $query) + protected function sortQuery(Builder $query): Builder { + $query = clone $query; $defaultSortName = $this->fields[0]; $direction = 'asc'; @@ -117,20 +118,21 @@ class ListingResponseBuilder $sortName = $defaultSortName; } - $query->orderBy($sortName, $direction); + return $query->orderBy($sortName, $direction); } /** * Apply count and offset for paging, based on params from the request while falling * back to system defined default, taking the max limit into account. */ - protected function applyCountAndOffset(Builder $query) + protected function countAndOffsetQuery(Builder $query): Builder { + $query = clone $query; $offset = max(0, $this->request->get('offset', 0)); $maxCount = config('api.max_item_count'); $count = $this->request->get('count', config('api.default_item_count')); $count = max(min($maxCount, $count), 1); - $query->skip($offset)->take($count); + return $query->skip($offset)->take($count); } } From 468fec80de7e32d2881eab2d7f7c40a2df872956 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 26 Apr 2020 09:26:41 +0100 Subject: [PATCH 044/197] Updated WYSIWYG callout shortcut to handle child elems - Will now search for a callout on/above the selected node rather than only using the selected node. - Issues previously where callout shortcut would not cycle if called when child formatting was currently selected inside the callout. For #2061 --- resources/js/components/wysiwyg-editor.js | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/resources/js/components/wysiwyg-editor.js b/resources/js/components/wysiwyg-editor.js index b8ce901ca..9ed00c078 100644 --- a/resources/js/components/wysiwyg-editor.js +++ b/resources/js/components/wysiwyg-editor.js @@ -98,21 +98,15 @@ function registerEditorShortcuts(editor) { // Loop through callout styles editor.shortcuts.add('meta+9', '', function() { - let selectedNode = editor.selection.getNode(); - let formats = ['info', 'success', 'warning', 'danger']; + const selectedNode = editor.selection.getNode(); + const callout = selectedNode ? selectedNode.closest('.callout') : null; - if (!selectedNode || selectedNode.className.indexOf('callout') === -1) { - editor.formatter.apply('calloutinfo'); - return; - } + const formats = ['info', 'success', 'warning', 'danger']; + const currentFormatIndex = formats.findIndex(format => callout && callout.classList.contains(format)); + const newFormatIndex = (currentFormatIndex + 1) % formats.length; + const newFormat = formats[newFormatIndex]; - for (let i = 0; i < formats.length; i++) { - if (selectedNode.className.indexOf(formats[i]) === -1) continue; - let newFormat = (i === formats.length -1) ? formats[0] : formats[i+1]; - editor.formatter.apply('callout' + newFormat); - return; - } - editor.formatter.apply('p'); + editor.formatter.apply('callout' + newFormat); }); } From 8ce38d2158d455ac18f7181119dcc4d68073eda9 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 26 Apr 2020 12:13:00 +0100 Subject: [PATCH 045/197] Fixed not shown existing-email warning on new ldap user - Reduced the amount of different exceptions from LDAP attempt so they can be handled more consistently. - Added test to cover. - Also cleaned up LDAP tests to reduce boilterplate mocks. Fixes #2048 --- app/Auth/Access/Guards/LdapSessionGuard.php | 8 +- app/Exceptions/NotifyException.php | 2 - tests/Auth/LdapTest.php | 140 +++++++++----------- 3 files changed, 66 insertions(+), 84 deletions(-) diff --git a/app/Auth/Access/Guards/LdapSessionGuard.php b/app/Auth/Access/Guards/LdapSessionGuard.php index 84f54ad29..652141c0c 100644 --- a/app/Auth/Access/Guards/LdapSessionGuard.php +++ b/app/Auth/Access/Guards/LdapSessionGuard.php @@ -60,10 +60,8 @@ class LdapSessionGuard extends ExternalBaseSessionGuard * @param array $credentials * @param bool $remember * @return bool - * @throws LoginAttemptEmailNeededException * @throws LoginAttemptException * @throws LdapException - * @throws UserRegistrationException */ public function attempt(array $credentials = [], $remember = false) { @@ -82,7 +80,11 @@ class LdapSessionGuard extends ExternalBaseSessionGuard } if (is_null($user)) { - $user = $this->createNewFromLdapAndCreds($userDetails, $credentials); + try { + $user = $this->createNewFromLdapAndCreds($userDetails, $credentials); + } catch (UserRegistrationException $exception) { + throw new LoginAttemptException($exception->message); + } } // Sync LDAP groups if required diff --git a/app/Exceptions/NotifyException.php b/app/Exceptions/NotifyException.php index 78ffde05c..4f8105960 100644 --- a/app/Exceptions/NotifyException.php +++ b/app/Exceptions/NotifyException.php @@ -8,8 +8,6 @@ class NotifyException extends \Exception /** * NotifyException constructor. - * @param string $message - * @param string $redirectLocation */ public function __construct(string $message, string $redirectLocation = "/") { diff --git a/tests/Auth/LdapTest.php b/tests/Auth/LdapTest.php index de86b9fb6..ed8748f08 100644 --- a/tests/Auth/LdapTest.php +++ b/tests/Auth/LdapTest.php @@ -63,11 +63,22 @@ class LdapTest extends BrowserKitTest ->press('Log In'); } + /** + * Set LDAP method mocks for things we commonly call without altering. + */ + protected function commonLdapMocks(int $connects = 1, int $versions = 1, int $options = 2, int $binds = 4, int $escapes = 2, int $explodes = 0) + { + $this->mockLdap->shouldReceive('connect')->times($connects)->andReturn($this->resourceId); + $this->mockLdap->shouldReceive('setVersion')->times($versions); + $this->mockLdap->shouldReceive('setOption')->times($options); + $this->mockLdap->shouldReceive('bind')->times($binds)->andReturn(true); + $this->mockEscapes($escapes); + $this->mockExplodes($explodes); + } + public function test_login() { - $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->once(); - $this->mockLdap->shouldReceive('setOption')->times(2); + $this->commonLdapMocks(1, 1, 2, 4, 2); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(2) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -75,8 +86,6 @@ class LdapTest extends BrowserKitTest 'cn' => [$this->mockUser->name], 'dn' => ['dc=test' . config('services.ldap.base_dn')] ]]); - $this->mockLdap->shouldReceive('bind')->times(4)->andReturn(true); - $this->mockEscapes(2); $this->mockUserLogin() ->seePageIs('/login')->see('Please enter an email to use for this account.'); @@ -94,9 +103,7 @@ class LdapTest extends BrowserKitTest 'registration-restrict' => 'testing.com' ]); - $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->once(); - $this->mockLdap->shouldReceive('setOption')->times(2); + $this->commonLdapMocks(1, 1, 2, 4, 2); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(2) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -104,8 +111,6 @@ class LdapTest extends BrowserKitTest 'cn' => [$this->mockUser->name], 'dn' => ['dc=test' . config('services.ldap.base_dn')] ]]); - $this->mockLdap->shouldReceive('bind')->times(4)->andReturn(true); - $this->mockEscapes(2); $this->mockUserLogin() ->seePageIs('/login') @@ -122,10 +127,9 @@ class LdapTest extends BrowserKitTest public function test_login_works_when_no_uid_provided_by_ldap_server() { - $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->once(); $ldapDn = 'cn=test-user,dc=test' . config('services.ldap.base_dn'); - $this->mockLdap->shouldReceive('setOption')->times(1); + + $this->commonLdapMocks(1, 1, 1, 2, 1); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(1) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -133,8 +137,6 @@ class LdapTest extends BrowserKitTest 'dn' => $ldapDn, 'mail' => [$this->mockUser->email] ]]); - $this->mockLdap->shouldReceive('bind')->times(2)->andReturn(true); - $this->mockEscapes(1); $this->mockUserLogin() ->seePageIs('/') @@ -145,10 +147,9 @@ class LdapTest extends BrowserKitTest public function test_a_custom_uid_attribute_can_be_specified_and_is_used_properly() { config()->set(['services.ldap.id_attribute' => 'my_custom_id']); - $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->once(); + + $this->commonLdapMocks(1, 1, 1, 2, 1); $ldapDn = 'cn=test-user,dc=test' . config('services.ldap.base_dn'); - $this->mockLdap->shouldReceive('setOption')->times(1); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(1) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -159,9 +160,6 @@ class LdapTest extends BrowserKitTest ]]); - $this->mockLdap->shouldReceive('bind')->times(2)->andReturn(true); - $this->mockEscapes(1); - $this->mockUserLogin() ->seePageIs('/') ->see($this->mockUser->name) @@ -170,9 +168,7 @@ class LdapTest extends BrowserKitTest public function test_initial_incorrect_credentials() { - $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->once(); - $this->mockLdap->shouldReceive('setOption')->times(1); + $this->commonLdapMocks(1, 1, 1, 0, 1); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(1) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -181,7 +177,6 @@ class LdapTest extends BrowserKitTest 'dn' => ['dc=test' . config('services.ldap.base_dn')] ]]); $this->mockLdap->shouldReceive('bind')->times(2)->andReturn(true, false); - $this->mockEscapes(1); $this->mockUserLogin() ->seePageIs('/login')->see('These credentials do not match our records.') @@ -190,14 +185,10 @@ class LdapTest extends BrowserKitTest public function test_login_not_found_username() { - $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->once(); - $this->mockLdap->shouldReceive('setOption')->times(1); + $this->commonLdapMocks(1, 1, 1, 1, 1); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(1) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 0]); - $this->mockLdap->shouldReceive('bind')->times(1)->andReturn(true, false); - $this->mockEscapes(1); $this->mockUserLogin() ->seePageIs('/login')->see('These credentials do not match our records.') @@ -257,9 +248,8 @@ class LdapTest extends BrowserKitTest 'services.ldap.group_attribute' => 'memberOf', 'services.ldap.remove_from_groups' => false, ]); - $this->mockLdap->shouldReceive('connect')->times(1)->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->times(1); - $this->mockLdap->shouldReceive('setOption')->times(4); + + $this->commonLdapMocks(1, 1, 4, 5, 4, 6); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(4) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -273,9 +263,6 @@ class LdapTest extends BrowserKitTest 1 => "cn=ldaptester-second,ou=groups,dc=example,dc=com", ] ]]); - $this->mockLdap->shouldReceive('bind')->times(5)->andReturn(true); - $this->mockEscapes(4); - $this->mockExplodes(6); $this->mockUserLogin()->seePageIs('/'); @@ -306,9 +293,8 @@ class LdapTest extends BrowserKitTest 'services.ldap.group_attribute' => 'memberOf', 'services.ldap.remove_from_groups' => true, ]); - $this->mockLdap->shouldReceive('connect')->times(1)->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->times(1); - $this->mockLdap->shouldReceive('setOption')->times(3); + + $this->commonLdapMocks(1, 1, 3, 4, 3, 2); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(3) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -321,9 +307,6 @@ class LdapTest extends BrowserKitTest 0 => "cn=ldaptester,ou=groups,dc=example,dc=com", ] ]]); - $this->mockLdap->shouldReceive('bind')->times(4)->andReturn(true); - $this->mockEscapes(3); - $this->mockExplodes(2); $this->mockUserLogin()->seePageIs('/'); @@ -355,9 +338,8 @@ class LdapTest extends BrowserKitTest 'services.ldap.group_attribute' => 'memberOf', 'services.ldap.remove_from_groups' => true, ]); - $this->mockLdap->shouldReceive('connect')->times(1)->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->times(1); - $this->mockLdap->shouldReceive('setOption')->times(3); + + $this->commonLdapMocks(1, 1, 3, 4, 3, 2); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(3) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -370,9 +352,6 @@ class LdapTest extends BrowserKitTest 0 => "cn=ex-auth-a,ou=groups,dc=example,dc=com", ] ]]); - $this->mockLdap->shouldReceive('bind')->times(4)->andReturn(true); - $this->mockEscapes(3); - $this->mockExplodes(2); $this->mockUserLogin()->seePageIs('/'); @@ -400,9 +379,8 @@ class LdapTest extends BrowserKitTest 'services.ldap.group_attribute' => 'memberOf', 'services.ldap.remove_from_groups' => true, ]); - $this->mockLdap->shouldReceive('connect')->times(1)->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->times(1); - $this->mockLdap->shouldReceive('setOption')->times(4); + + $this->commonLdapMocks(1, 1, 4, 5, 4, 6); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(4) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -416,9 +394,6 @@ class LdapTest extends BrowserKitTest 1 => "cn=ldaptester-second,ou=groups,dc=example,dc=com", ] ]]); - $this->mockLdap->shouldReceive('bind')->times(5)->andReturn(true); - $this->mockEscapes(4); - $this->mockExplodes(6); $this->mockUserLogin()->seePageIs('/'); @@ -439,9 +414,7 @@ class LdapTest extends BrowserKitTest 'services.ldap.display_name_attribute' => 'displayName' ]); - $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->once(); - $this->mockLdap->shouldReceive('setOption')->times(2); + $this->commonLdapMocks(1, 1, 2, 4, 2); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(2) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -450,8 +423,6 @@ class LdapTest extends BrowserKitTest 'dn' => ['dc=test' . config('services.ldap.base_dn')], 'displayname' => 'displayNameAttribute' ]]); - $this->mockLdap->shouldReceive('bind')->times(4)->andReturn(true); - $this->mockEscapes(2); $this->mockUserLogin() ->seePageIs('/login')->see('Please enter an email to use for this account.'); @@ -469,9 +440,7 @@ class LdapTest extends BrowserKitTest 'services.ldap.display_name_attribute' => 'displayName' ]); - $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->once(); - $this->mockLdap->shouldReceive('setOption')->times(2); + $this->commonLdapMocks(1, 1, 2, 4, 2); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(2) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -479,8 +448,6 @@ class LdapTest extends BrowserKitTest 'cn' => [$this->mockUser->name], 'dn' => ['dc=test' . config('services.ldap.base_dn')] ]]); - $this->mockLdap->shouldReceive('bind')->times(4)->andReturn(true); - $this->mockEscapes(2); $this->mockUserLogin() ->seePageIs('/login')->see('Please enter an email to use for this account.'); @@ -499,15 +466,12 @@ class LdapTest extends BrowserKitTest ]); // Standard mocks - $this->mockLdap->shouldReceive('setVersion')->once(); - $this->mockLdap->shouldReceive('setOption')->times(1); + $this->commonLdapMocks(0, 1, 1, 2, 1); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(1)->andReturn(['count' => 1, 0 => [ 'uid' => [$this->mockUser->name], 'cn' => [$this->mockUser->name], 'dn' => ['dc=test' . config('services.ldap.base_dn')] ]]); - $this->mockLdap->shouldReceive('bind')->times(2)->andReturn(true); - $this->mockEscapes(1); $this->mockLdap->shouldReceive('connect')->once() ->with($expectedHost, $expectedPort)->andReturn($this->resourceId); @@ -567,9 +531,7 @@ class LdapTest extends BrowserKitTest { config()->set(['services.ldap.dump_user_details' => true]); - $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->once(); - $this->mockLdap->shouldReceive('setOption')->times(1); + $this->commonLdapMocks(1, 1, 1, 1, 1); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(1) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) ->andReturn(['count' => 1, 0 => [ @@ -577,8 +539,6 @@ class LdapTest extends BrowserKitTest 'cn' => [$this->mockUser->name], 'dn' => ['dc=test' . config('services.ldap.base_dn')] ]]); - $this->mockLdap->shouldReceive('bind')->times(1)->andReturn(true); - $this->mockEscapes(1); $this->post('/login', [ 'username' => $this->mockUser->name, @@ -594,10 +554,7 @@ class LdapTest extends BrowserKitTest { config()->set(['services.ldap.id_attribute' => 'BIN;uid']); $ldapService = app()->make(LdapService::class); - - $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); - $this->mockLdap->shouldReceive('setVersion')->once(); - $this->mockLdap->shouldReceive('setOption')->times(1); + $this->commonLdapMocks(1, 1, 1, 1, 1); $this->mockLdap->shouldReceive('searchAndGetEntries')->times(1) ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), ['cn', 'dn', 'uid', 'mail', 'cn']) ->andReturn(['count' => 1, 0 => [ @@ -605,10 +562,35 @@ class LdapTest extends BrowserKitTest 'cn' => [$this->mockUser->name], 'dn' => ['dc=test' . config('services.ldap.base_dn')] ]]); - $this->mockLdap->shouldReceive('bind')->times(1)->andReturn(true); - $this->mockEscapes(1); $details = $ldapService->getUserDetails('test'); $this->assertEquals('fff8f7', $details['uid']); } + + public function test_new_ldap_user_login_with_already_used_email_address_shows_error_message_to_user() + { + $this->commonLdapMocks(1, 1, 2, 4, 2); + $this->mockLdap->shouldReceive('searchAndGetEntries')->times(2) + ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) + ->andReturn(['count' => 1, 0 => [ + 'uid' => [$this->mockUser->name], + 'cn' => [$this->mockUser->name], + 'dn' => ['dc=test' . config('services.ldap.base_dn')], + 'mail' => 'tester@example.com', + ]], ['count' => 1, 0 => [ + 'uid' => ['Barry'], + 'cn' => ['Scott'], + 'dn' => ['dc=bscott' . config('services.ldap.base_dn')], + 'mail' => 'tester@example.com', + ]]); + + // First user login + $this->mockUserLogin()->seePageIs('/'); + + // Second user login + auth()->logout(); + $this->post('/login', ['username' => 'bscott', 'password' => 'pass'])->followRedirects(); + + $this->see('A user with the email tester@example.com already exists but with different credentials'); + } } From 4ef362143bf9f2508b69da260e07ba0330ca6edf Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 27 Apr 2020 15:54:39 +0100 Subject: [PATCH 046/197] Added auto-focus behaviour to page editor - Will focus on title if the value of the field matches the default text for the current user's language. - Otherwise will focus on the editor body. - Added and tested on both editors. For #2036 --- resources/js/components/markdown-editor.js | 5 +++++ resources/js/components/wysiwyg-editor.js | 4 ++++ resources/js/vues/page-editor.js | 25 ++++++++++++++++++---- resources/views/pages/form.blade.php | 4 ++-- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/resources/js/components/markdown-editor.js b/resources/js/components/markdown-editor.js index 4dc240d48..cc9a7b859 100644 --- a/resources/js/components/markdown-editor.js +++ b/resources/js/components/markdown-editor.js @@ -557,6 +557,11 @@ class MarkdownEditor { const prependLineCount = markdown.split('\n').length; this.cm.setCursor(cursorPos.line + prependLineCount, cursorPos.ch); }); + + // Focus on editor + window.$events.listen('editor::focus', () => { + this.cm.focus(); + }); } } diff --git a/resources/js/components/wysiwyg-editor.js b/resources/js/components/wysiwyg-editor.js index 9ed00c078..1c8c71099 100644 --- a/resources/js/components/wysiwyg-editor.js +++ b/resources/js/components/wysiwyg-editor.js @@ -402,6 +402,10 @@ function listenForBookStackEditorEvents(editor) { editor.setContent(content); }); + // Focus on the editor + window.$events.listen('editor::focus', () => { + editor.focus(); + }); } class WysiwygEditor { diff --git a/resources/js/vues/page-editor.js b/resources/js/vues/page-editor.js index fbf2857a4..a79ad2049 100644 --- a/resources/js/vues/page-editor.js +++ b/resources/js/vues/page-editor.js @@ -19,6 +19,8 @@ function mounted() { this.pageId= Number(elem.getAttribute('page-id')); this.isNewDraft = Number(elem.getAttribute('page-new-draft')) === 1; this.isUpdateDraft = Number(elem.getAttribute('page-update-draft')) === 1; + this.titleElem = elem.querySelector('input[name=name]'); + this.hasDefaultTitle = this.titleElem.closest('[is-default-value]') !== null; if (this.pageId !== 0 && this.draftsEnabled) { window.setTimeout(() => { @@ -43,6 +45,8 @@ function mounted() { window.$events.listen('editor-markdown-change', markdown => { this.editorMarkdown = markdown; }); + + this.setInitialFocus(); } let data = { @@ -58,18 +62,31 @@ let data = { editorHTML: '', editorMarkdown: '', + + hasDefaultTitle: false, + titleElem: null, }; let methods = { + setInitialFocus() { + if (this.hasDefaultTitle) { + this.titleElem.select(); + } else { + window.setTimeout(() => { + this.$events.emit('editor::focus', ''); + }, 500); + } + }, + startAutoSave() { - currentContent.title = document.getElementById('name').value.trim(); + currentContent.title = this.titleElem.value.trim(); currentContent.html = this.editorHTML; autoSave = window.setInterval(() => { // Return if manually saved recently to prevent bombarding the server if (Date.now() - lastSave < (1000 * autoSaveFrequency)/2) return; - const newTitle = document.getElementById('name').value.trim(); + const newTitle = this.titleElem.value.trim(); const newHtml = this.editorHTML; if (newTitle !== currentContent.title || newHtml !== currentContent.html) { @@ -85,7 +102,7 @@ let methods = { if (!this.draftsEnabled) return; const data = { - name: document.getElementById('name').value.trim(), + name: this.titleElem.value.trim(), html: this.editorHTML }; @@ -126,7 +143,7 @@ let methods = { window.$events.emit('editor-html-update', response.data.html); window.$events.emit('editor-markdown-update', response.data.markdown || response.data.html); - document.getElementById('name').value = response.data.name; + this.titleElem.value = response.data.name; window.setTimeout(() => { this.startAutoSave(); }, 1000); diff --git a/resources/views/pages/form.blade.php b/resources/views/pages/form.blade.php index 3c2b4f0b0..4294ff56b 100644 --- a/resources/views/pages/form.blade.php +++ b/resources/views/pages/form.blade.php @@ -63,8 +63,8 @@ {{--Title input--}}
    -
    - @include('form.text', ['name' => 'name', 'placeholder' => trans('entities.pages_title')]) +
    name === trans('entities.pages_initial_name')) is-default-value @endif> + @include('form.text', ['name' => 'name', 'model' => $model, 'placeholder' => trans('entities.pages_title')])
    From 898d0b5817fc776746d10b7dd27b7d4940d83e76 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 27 Apr 2020 16:53:27 +0100 Subject: [PATCH 047/197] Added multi-select to book-sort interface As discussed in #2064 Closes #2067 --- resources/js/components/book-sort.js | 6 +++++- resources/sass/_lists.scss | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/resources/js/components/book-sort.js b/resources/js/components/book-sort.js index da2b28d8e..b0d64ad17 100644 --- a/resources/js/components/book-sort.js +++ b/resources/js/components/book-sort.js @@ -1,4 +1,4 @@ -import Sortable from "sortablejs"; +import {Sortable, MultiDrag} from "sortablejs"; // Auto sort control const sortOperations = { @@ -43,6 +43,7 @@ class BookSort { this.input = elem.querySelector('[book-sort-input]'); const initialSortBox = elem.querySelector('.sort-box'); + Sortable.mount(new MultiDrag()); this.setupBookSortable(initialSortBox); this.setupSortPresets(); @@ -134,6 +135,9 @@ class BookSort { onSort: this.updateMapInput.bind(this), dragClass: 'bg-white', ghostClass: 'primary-background-light', + multiDrag: true, + multiDragKey: 'CTRL', + selectedClass: 'sortable-selected', }); } } diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 32c56f385..77727060e 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -275,6 +275,10 @@ .entity-list-item > span:first-child { align-self: flex-start; } + .sortable-selected .entity-list-item, .sortable-selected .entity-list-item:hover { + outline: 1px dotted var(--color-primary); + background-color: var(--color-primary-light) !important; + } .entity-list-item > div { display: block; flex: 1; From 6f2a2c05bf28b6976f3f8a464b581e318cf887bf Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 28 Apr 2020 10:19:42 +0100 Subject: [PATCH 048/197] New Crowdin translations (#2028) * New translations settings.php (Chinese Simplified) * New translations common.php (Spanish) * New translations common.php (Spanish, Argentina) * New translations common.php (Turkish) * New translations common.php (French) * New translations auth.php (Dutch) * New translations common.php (Dutch) * New translations entities.php (Dutch) * New translations activities.php (Thai) * New translations auth.php (Thai) * New translations common.php (Thai) * New translations components.php (Thai) * New translations entities.php (Thai) * New translations errors.php (Thai) * New translations pagination.php (Thai) * New translations passwords.php (Thai) * New translations settings.php (Thai) * New translations validation.php (Thai) --- resources/lang/es/common.php | 4 +- resources/lang/es_AR/common.php | 4 +- resources/lang/fr/common.php | 4 +- resources/lang/nl/auth.php | 2 +- resources/lang/nl/common.php | 6 +- resources/lang/nl/entities.php | 2 +- resources/lang/th/activities.php | 48 +++++ resources/lang/th/auth.php | 77 ++++++++ resources/lang/th/common.php | 79 ++++++++ resources/lang/th/components.php | 33 ++++ resources/lang/th/entities.php | 314 ++++++++++++++++++++++++++++++ resources/lang/th/errors.php | 103 ++++++++++ resources/lang/th/pagination.php | 12 ++ resources/lang/th/passwords.php | 15 ++ resources/lang/th/settings.php | 214 ++++++++++++++++++++ resources/lang/th/validation.php | 114 +++++++++++ resources/lang/tr/common.php | 4 +- resources/lang/zh_CN/settings.php | 6 +- 18 files changed, 1025 insertions(+), 16 deletions(-) create mode 100644 resources/lang/th/activities.php create mode 100644 resources/lang/th/auth.php create mode 100644 resources/lang/th/common.php create mode 100644 resources/lang/th/components.php create mode 100644 resources/lang/th/entities.php create mode 100644 resources/lang/th/errors.php create mode 100644 resources/lang/th/pagination.php create mode 100644 resources/lang/th/passwords.php create mode 100644 resources/lang/th/settings.php create mode 100644 resources/lang/th/validation.php diff --git a/resources/lang/es/common.php b/resources/lang/es/common.php index b61b170b1..4f4f7f600 100644 --- a/resources/lang/es/common.php +++ b/resources/lang/es/common.php @@ -66,8 +66,8 @@ return [ 'profile_menu' => 'Menú de Perfil', 'view_profile' => 'Ver Perfil', 'edit_profile' => 'Editar Perfil', - 'dark_mode' => 'Dark Mode', - 'light_mode' => 'Light Mode', + 'dark_mode' => 'Modo Oscuro', + 'light_mode' => 'Modo Claro', // Layout tabs 'tab_info' => 'Información', diff --git a/resources/lang/es_AR/common.php b/resources/lang/es_AR/common.php index 5f98271ac..0051e9c22 100644 --- a/resources/lang/es_AR/common.php +++ b/resources/lang/es_AR/common.php @@ -66,8 +66,8 @@ return [ 'profile_menu' => 'Menu del Perfil', 'view_profile' => 'Ver Perfil', 'edit_profile' => 'Editar Perfil', - 'dark_mode' => 'Dark Mode', - 'light_mode' => 'Light Mode', + 'dark_mode' => 'Modo Oscuro', + 'light_mode' => 'Modo Claro', // Layout tabs 'tab_info' => 'Información', diff --git a/resources/lang/fr/common.php b/resources/lang/fr/common.php index 4294c3d27..81dde84c4 100644 --- a/resources/lang/fr/common.php +++ b/resources/lang/fr/common.php @@ -66,8 +66,8 @@ return [ 'profile_menu' => 'Menu du profil', 'view_profile' => 'Voir le profil', 'edit_profile' => 'Modifier le profil', - 'dark_mode' => 'Dark Mode', - 'light_mode' => 'Light Mode', + 'dark_mode' => 'Mode sombre', + 'light_mode' => 'Mode clair', // Layout tabs 'tab_info' => 'Informations', diff --git a/resources/lang/nl/auth.php b/resources/lang/nl/auth.php index 03211e1b9..ce0be87ed 100644 --- a/resources/lang/nl/auth.php +++ b/resources/lang/nl/auth.php @@ -43,7 +43,7 @@ return [ 'reset_password' => 'Wachtwoord Herstellen', 'reset_password_send_instructions' => 'Geef je e-mail en we sturen je een link om je wachtwoord te herstellen', 'reset_password_send_button' => 'Link Sturen', - 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', + 'reset_password_sent' => 'Een link om het wachtwoord te resetten zal verstuurd worden naar :email als dat e-mailadres in het systeem gevonden is.', 'reset_password_success' => 'Je wachtwoord is succesvol hersteld.', 'email_reset_subject' => 'Herstel je wachtwoord van :appName', 'email_reset_text' => 'Je ontvangt deze e-mail zodat je je wachtwoord kunt herstellen.', diff --git a/resources/lang/nl/common.php b/resources/lang/nl/common.php index 2351ab2db..f228fa6c4 100644 --- a/resources/lang/nl/common.php +++ b/resources/lang/nl/common.php @@ -35,7 +35,7 @@ return [ 'delete' => 'Verwijder', 'search' => 'Zoek', 'search_clear' => 'Zoekopdracht wissen', - 'reset' => 'Reset', + 'reset' => 'Resetten', 'remove' => 'Verwijderen', 'add' => 'Toevoegen', 'fullscreen' => 'Volledig scherm', @@ -66,8 +66,8 @@ return [ 'profile_menu' => 'Profiel menu', 'view_profile' => 'Profiel Weergeven', 'edit_profile' => 'Profiel Bewerken', - 'dark_mode' => 'Dark Mode', - 'light_mode' => 'Light Mode', + 'dark_mode' => 'Donkere Modus', + 'light_mode' => 'Lichte Modus', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/lang/nl/entities.php b/resources/lang/nl/entities.php index bcd069053..a88be7711 100644 --- a/resources/lang/nl/entities.php +++ b/resources/lang/nl/entities.php @@ -11,7 +11,7 @@ return [ 'recently_updated_pages' => 'Recent Bijgewerkte Pagina\'s', 'recently_created_chapters' => 'Recent Aangemaakte Hoofdstukken', 'recently_created_books' => 'Recent Aangemaakte Boeken', - 'recently_created_shelves' => 'Recently Created Shelves', + 'recently_created_shelves' => 'Recent Aangemaakte Boekenplanken', 'recently_update' => 'Recent Bijgewerkt', 'recently_viewed' => 'Recent Bekeken', 'recent_activity' => 'Recente Activiteit', diff --git a/resources/lang/th/activities.php b/resources/lang/th/activities.php new file mode 100644 index 000000000..4cac54b2a --- /dev/null +++ b/resources/lang/th/activities.php @@ -0,0 +1,48 @@ + 'created page', + 'page_create_notification' => 'Page Successfully Created', + 'page_update' => 'updated page', + 'page_update_notification' => 'Page Successfully Updated', + 'page_delete' => 'deleted page', + 'page_delete_notification' => 'Page Successfully Deleted', + 'page_restore' => 'restored page', + 'page_restore_notification' => 'Page Successfully Restored', + 'page_move' => 'moved page', + + // Chapters + 'chapter_create' => 'created chapter', + 'chapter_create_notification' => 'Chapter Successfully Created', + 'chapter_update' => 'updated chapter', + 'chapter_update_notification' => 'Chapter Successfully Updated', + 'chapter_delete' => 'deleted chapter', + 'chapter_delete_notification' => 'Chapter Successfully Deleted', + 'chapter_move' => 'moved chapter', + + // Books + 'book_create' => 'created book', + 'book_create_notification' => 'Book Successfully Created', + 'book_update' => 'updated book', + 'book_update_notification' => 'Book Successfully Updated', + 'book_delete' => 'deleted book', + 'book_delete_notification' => 'Book Successfully Deleted', + 'book_sort' => 'sorted book', + 'book_sort_notification' => 'Book Successfully Re-sorted', + + // Bookshelves + 'bookshelf_create' => 'created Bookshelf', + 'bookshelf_create_notification' => 'Bookshelf Successfully Created', + 'bookshelf_update' => 'updated bookshelf', + 'bookshelf_update_notification' => 'Bookshelf Successfully Updated', + 'bookshelf_delete' => 'deleted bookshelf', + 'bookshelf_delete_notification' => 'Bookshelf Successfully Deleted', + + // Other + 'commented_on' => 'commented on', +]; diff --git a/resources/lang/th/auth.php b/resources/lang/th/auth.php new file mode 100644 index 000000000..d64fce93a --- /dev/null +++ b/resources/lang/th/auth.php @@ -0,0 +1,77 @@ + 'These credentials do not match our records.', + 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', + + // Login & Register + 'sign_up' => 'Sign up', + 'log_in' => 'Log in', + 'log_in_with' => 'Login with :socialDriver', + 'sign_up_with' => 'Sign up with :socialDriver', + 'logout' => 'Logout', + + 'name' => 'Name', + 'username' => 'Username', + 'email' => 'Email', + 'password' => 'Password', + 'password_confirm' => 'Confirm Password', + 'password_hint' => 'Must be over 7 characters', + 'forgot_password' => 'Forgot Password?', + 'remember_me' => 'Remember Me', + 'ldap_email_hint' => 'Please enter an email to use for this account.', + 'create_account' => 'Create Account', + 'already_have_account' => 'Already have an account?', + 'dont_have_account' => 'Don\'t have an account?', + 'social_login' => 'Social Login', + 'social_registration' => 'Social Registration', + 'social_registration_text' => 'Register and sign in using another service.', + + 'register_thanks' => 'Thanks for registering!', + 'register_confirm' => 'Please check your email and click the confirmation button to access :appName.', + 'registrations_disabled' => 'Registrations are currently disabled', + 'registration_email_domain_invalid' => 'That email domain does not have access to this application', + 'register_success' => 'Thanks for signing up! You are now registered and signed in.', + + + // Password Reset + 'reset_password' => 'Reset Password', + 'reset_password_send_instructions' => 'Enter your email below and you will be sent an email with a password reset link.', + 'reset_password_send_button' => 'Send Reset Link', + 'reset_password_sent' => 'A password reset link will be sent to :email if that email address is found in the system.', + 'reset_password_success' => 'Your password has been successfully reset.', + 'email_reset_subject' => 'Reset your :appName password', + 'email_reset_text' => 'You are receiving this email because we received a password reset request for your account.', + 'email_reset_not_requested' => 'If you did not request a password reset, no further action is required.', + + + // Email Confirmation + 'email_confirm_subject' => 'Confirm your email on :appName', + 'email_confirm_greeting' => 'Thanks for joining :appName!', + 'email_confirm_text' => 'Please confirm your email address by clicking the button below:', + 'email_confirm_action' => 'Confirm Email', + 'email_confirm_send_error' => 'Email confirmation required but the system could not send the email. Contact the admin to ensure email is set up correctly.', + 'email_confirm_success' => 'Your email has been confirmed!', + 'email_confirm_resent' => 'Confirmation email resent, Please check your inbox.', + + 'email_not_confirmed' => 'Email Address Not Confirmed', + 'email_not_confirmed_text' => 'Your email address has not yet been confirmed.', + 'email_not_confirmed_click_link' => 'Please click the link in the email that was sent shortly after you registered.', + 'email_not_confirmed_resend' => 'If you cannot find the email you can re-send the confirmation email by submitting the form below.', + 'email_not_confirmed_resend_button' => 'Resend Confirmation Email', + + // User Invite + 'user_invite_email_subject' => 'You have been invited to join :appName!', + 'user_invite_email_greeting' => 'An account has been created for you on :appName.', + 'user_invite_email_text' => 'Click the button below to set an account password and gain access:', + 'user_invite_email_action' => 'Set Account Password', + 'user_invite_page_welcome' => 'Welcome to :appName!', + 'user_invite_page_text' => 'To finalise your account and gain access you need to set a password which will be used to log-in to :appName on future visits.', + 'user_invite_page_confirm_button' => 'Confirm Password', + 'user_invite_success' => 'Password set, you now have access to :appName!' +]; \ No newline at end of file diff --git a/resources/lang/th/common.php b/resources/lang/th/common.php new file mode 100644 index 000000000..68c58b92b --- /dev/null +++ b/resources/lang/th/common.php @@ -0,0 +1,79 @@ + 'Cancel', + 'confirm' => 'Confirm', + 'back' => 'Back', + 'save' => 'Save', + 'continue' => 'Continue', + 'select' => 'Select', + 'toggle_all' => 'Toggle All', + 'more' => 'More', + + // Form Labels + 'name' => 'Name', + 'description' => 'Description', + 'role' => 'Role', + 'cover_image' => 'Cover image', + 'cover_image_description' => 'This image should be approx 440x250px.', + + // Actions + 'actions' => 'Actions', + 'view' => 'View', + 'view_all' => 'View All', + 'create' => 'Create', + 'update' => 'Update', + 'edit' => 'Edit', + 'sort' => 'Sort', + 'move' => 'Move', + 'copy' => 'Copy', + 'reply' => 'Reply', + 'delete' => 'Delete', + 'search' => 'Search', + 'search_clear' => 'Clear Search', + 'reset' => 'Reset', + 'remove' => 'Remove', + 'add' => 'Add', + 'fullscreen' => 'Fullscreen', + + // Sort Options + 'sort_options' => 'Sort Options', + 'sort_direction_toggle' => 'Sort Direction Toggle', + 'sort_ascending' => 'Sort Ascending', + 'sort_descending' => 'Sort Descending', + 'sort_name' => 'Name', + 'sort_created_at' => 'Created Date', + 'sort_updated_at' => 'Updated Date', + + // Misc + 'deleted_user' => 'Deleted User', + 'no_activity' => 'No activity to show', + 'no_items' => 'No items available', + 'back_to_top' => 'Back to top', + 'toggle_details' => 'Toggle Details', + 'toggle_thumbnails' => 'Toggle Thumbnails', + 'details' => 'Details', + 'grid_view' => 'Grid View', + 'list_view' => 'List View', + 'default' => 'Default', + 'breadcrumb' => 'Breadcrumb', + + // Header + 'profile_menu' => 'Profile Menu', + 'view_profile' => 'View Profile', + 'edit_profile' => 'Edit Profile', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', + + // Layout tabs + 'tab_info' => 'Info', + 'tab_content' => 'Content', + + // Email Content + 'email_action_help' => 'If you’re having trouble clicking the ":actionText" button, copy and paste the URL below into your web browser:', + 'email_rights' => 'All rights reserved', +]; diff --git a/resources/lang/th/components.php b/resources/lang/th/components.php new file mode 100644 index 000000000..d8e8981fb --- /dev/null +++ b/resources/lang/th/components.php @@ -0,0 +1,33 @@ + 'Image Select', + 'image_all' => 'All', + 'image_all_title' => 'View all images', + 'image_book_title' => 'View images uploaded to this book', + 'image_page_title' => 'View images uploaded to this page', + 'image_search_hint' => 'Search by image name', + 'image_uploaded' => 'Uploaded :uploadedDate', + 'image_load_more' => 'Load More', + 'image_image_name' => 'Image Name', + 'image_delete_used' => 'This image is used in the pages below.', + 'image_delete_confirm' => 'Click delete again to confirm you want to delete this image.', + 'image_select_image' => 'Select Image', + 'image_dropzone' => 'Drop images or click here to upload', + 'images_deleted' => 'Images Deleted', + 'image_preview' => 'Image Preview', + 'image_upload_success' => 'Image uploaded successfully', + 'image_update_success' => 'Image details successfully updated', + 'image_delete_success' => 'Image successfully deleted', + 'image_upload_remove' => 'Remove', + + // Code Editor + 'code_editor' => 'Edit Code', + 'code_language' => 'Code Language', + 'code_content' => 'Code Content', + 'code_save' => 'Save Code', +]; diff --git a/resources/lang/th/entities.php b/resources/lang/th/entities.php new file mode 100644 index 000000000..6bbc723b0 --- /dev/null +++ b/resources/lang/th/entities.php @@ -0,0 +1,314 @@ + 'Recently Created', + 'recently_created_pages' => 'Recently Created Pages', + 'recently_updated_pages' => 'Recently Updated Pages', + 'recently_created_chapters' => 'Recently Created Chapters', + 'recently_created_books' => 'Recently Created Books', + 'recently_created_shelves' => 'Recently Created Shelves', + 'recently_update' => 'Recently Updated', + 'recently_viewed' => 'Recently Viewed', + 'recent_activity' => 'Recent Activity', + 'create_now' => 'Create one now', + 'revisions' => 'Revisions', + 'meta_revision' => 'Revision #:revisionCount', + 'meta_created' => 'Created :timeLength', + 'meta_created_name' => 'Created :timeLength by :user', + 'meta_updated' => 'Updated :timeLength', + 'meta_updated_name' => 'Updated :timeLength by :user', + 'entity_select' => 'Entity Select', + 'images' => 'Images', + 'my_recent_drafts' => 'My Recent Drafts', + 'my_recently_viewed' => 'My Recently Viewed', + 'no_pages_viewed' => 'You have not viewed any pages', + 'no_pages_recently_created' => 'No pages have been recently created', + 'no_pages_recently_updated' => 'No pages have been recently updated', + 'export' => 'Export', + 'export_html' => 'Contained Web File', + 'export_pdf' => 'PDF File', + 'export_text' => 'Plain Text File', + + // Permissions and restrictions + 'permissions' => 'Permissions', + 'permissions_intro' => 'Once enabled, These permissions will take priority over any set role permissions.', + 'permissions_enable' => 'Enable Custom Permissions', + 'permissions_save' => 'Save Permissions', + + // Search + 'search_results' => 'Search Results', + 'search_total_results_found' => ':count result found|:count total results found', + 'search_clear' => 'Clear Search', + 'search_no_pages' => 'No pages matched this search', + 'search_for_term' => 'Search for :term', + 'search_more' => 'More Results', + 'search_filters' => 'Search Filters', + 'search_content_type' => 'Content Type', + 'search_exact_matches' => 'Exact Matches', + 'search_tags' => 'Tag Searches', + 'search_options' => 'Options', + 'search_viewed_by_me' => 'Viewed by me', + 'search_not_viewed_by_me' => 'Not viewed by me', + 'search_permissions_set' => 'Permissions set', + 'search_created_by_me' => 'Created by me', + 'search_updated_by_me' => 'Updated by me', + 'search_date_options' => 'Date Options', + 'search_updated_before' => 'Updated before', + 'search_updated_after' => 'Updated after', + 'search_created_before' => 'Created before', + 'search_created_after' => 'Created after', + 'search_set_date' => 'Set Date', + 'search_update' => 'Update Search', + + // Shelves + 'shelf' => 'Shelf', + 'shelves' => 'Shelves', + 'x_shelves' => ':count Shelf|:count Shelves', + 'shelves_long' => 'Bookshelves', + 'shelves_empty' => 'No shelves have been created', + 'shelves_create' => 'Create New Shelf', + 'shelves_popular' => 'Popular Shelves', + 'shelves_new' => 'New Shelves', + 'shelves_new_action' => 'New Shelf', + 'shelves_popular_empty' => 'The most popular shelves will appear here.', + 'shelves_new_empty' => 'The most recently created shelves will appear here.', + 'shelves_save' => 'Save Shelf', + 'shelves_books' => 'Books on this shelf', + 'shelves_add_books' => 'Add books to this shelf', + 'shelves_drag_books' => 'Drag books here to add them to this shelf', + 'shelves_empty_contents' => 'This shelf has no books assigned to it', + 'shelves_edit_and_assign' => 'Edit shelf to assign books', + 'shelves_edit_named' => 'Edit Bookshelf :name', + 'shelves_edit' => 'Edit Bookshelf', + 'shelves_delete' => 'Delete Bookshelf', + 'shelves_delete_named' => 'Delete Bookshelf :name', + 'shelves_delete_explain' => "This will delete the bookshelf with the name ':name'. Contained books will not be deleted.", + 'shelves_delete_confirmation' => 'Are you sure you want to delete this bookshelf?', + 'shelves_permissions' => 'Bookshelf Permissions', + 'shelves_permissions_updated' => 'Bookshelf Permissions Updated', + 'shelves_permissions_active' => 'Bookshelf Permissions Active', + 'shelves_copy_permissions_to_books' => 'Copy Permissions to Books', + 'shelves_copy_permissions' => 'Copy Permissions', + 'shelves_copy_permissions_explain' => 'This will apply the current permission settings of this bookshelf to all books contained within. Before activating, ensure any changes to the permissions of this bookshelf have been saved.', + 'shelves_copy_permission_success' => 'Bookshelf permissions copied to :count books', + + // Books + 'book' => 'Book', + 'books' => 'Books', + 'x_books' => ':count Book|:count Books', + 'books_empty' => 'No books have been created', + 'books_popular' => 'Popular Books', + 'books_recent' => 'Recent Books', + 'books_new' => 'New Books', + 'books_new_action' => 'New Book', + 'books_popular_empty' => 'The most popular books will appear here.', + 'books_new_empty' => 'The most recently created books will appear here.', + 'books_create' => 'Create New Book', + 'books_delete' => 'Delete Book', + 'books_delete_named' => 'Delete Book :bookName', + 'books_delete_explain' => 'This will delete the book with the name \':bookName\'. All pages and chapters will be removed.', + 'books_delete_confirmation' => 'Are you sure you want to delete this book?', + 'books_edit' => 'Edit Book', + 'books_edit_named' => 'Edit Book :bookName', + 'books_form_book_name' => 'Book Name', + 'books_save' => 'Save Book', + 'books_permissions' => 'Book Permissions', + 'books_permissions_updated' => 'Book Permissions Updated', + 'books_empty_contents' => 'No pages or chapters have been created for this book.', + 'books_empty_create_page' => 'Create a new page', + 'books_empty_sort_current_book' => 'Sort the current book', + 'books_empty_add_chapter' => 'Add a chapter', + 'books_permissions_active' => 'Book Permissions Active', + 'books_search_this' => 'Search this book', + 'books_navigation' => 'Book Navigation', + 'books_sort' => 'Sort Book Contents', + 'books_sort_named' => 'Sort Book :bookName', + 'books_sort_name' => 'Sort by Name', + 'books_sort_created' => 'Sort by Created Date', + 'books_sort_updated' => 'Sort by Updated Date', + 'books_sort_chapters_first' => 'Chapters First', + 'books_sort_chapters_last' => 'Chapters Last', + 'books_sort_show_other' => 'Show Other Books', + 'books_sort_save' => 'Save New Order', + + // Chapters + 'chapter' => 'Chapter', + 'chapters' => 'Chapters', + 'x_chapters' => ':count Chapter|:count Chapters', + 'chapters_popular' => 'Popular Chapters', + 'chapters_new' => 'New Chapter', + 'chapters_create' => 'Create New Chapter', + 'chapters_delete' => 'Delete Chapter', + 'chapters_delete_named' => 'Delete Chapter :chapterName', + 'chapters_delete_explain' => 'This will delete the chapter with the name \':chapterName\'. All pages will be removed and added directly to the parent book.', + 'chapters_delete_confirm' => 'Are you sure you want to delete this chapter?', + 'chapters_edit' => 'Edit Chapter', + 'chapters_edit_named' => 'Edit Chapter :chapterName', + 'chapters_save' => 'Save Chapter', + 'chapters_move' => 'Move Chapter', + 'chapters_move_named' => 'Move Chapter :chapterName', + 'chapter_move_success' => 'Chapter moved to :bookName', + 'chapters_permissions' => 'Chapter Permissions', + 'chapters_empty' => 'No pages are currently in this chapter.', + 'chapters_permissions_active' => 'Chapter Permissions Active', + 'chapters_permissions_success' => 'Chapter Permissions Updated', + 'chapters_search_this' => 'Search this chapter', + + // Pages + 'page' => 'Page', + 'pages' => 'Pages', + 'x_pages' => ':count Page|:count Pages', + 'pages_popular' => 'Popular Pages', + 'pages_new' => 'New Page', + 'pages_attachments' => 'Attachments', + 'pages_navigation' => 'Page Navigation', + 'pages_delete' => 'Delete Page', + 'pages_delete_named' => 'Delete Page :pageName', + 'pages_delete_draft_named' => 'Delete Draft Page :pageName', + 'pages_delete_draft' => 'Delete Draft Page', + 'pages_delete_success' => 'Page deleted', + 'pages_delete_draft_success' => 'Draft page deleted', + 'pages_delete_confirm' => 'Are you sure you want to delete this page?', + 'pages_delete_draft_confirm' => 'Are you sure you want to delete this draft page?', + 'pages_editing_named' => 'Editing Page :pageName', + 'pages_edit_draft_options' => 'Draft Options', + 'pages_edit_save_draft' => 'Save Draft', + 'pages_edit_draft' => 'Edit Page Draft', + 'pages_editing_draft' => 'Editing Draft', + 'pages_editing_page' => 'Editing Page', + 'pages_edit_draft_save_at' => 'Draft saved at ', + 'pages_edit_delete_draft' => 'Delete Draft', + 'pages_edit_discard_draft' => 'Discard Draft', + 'pages_edit_set_changelog' => 'Set Changelog', + 'pages_edit_enter_changelog_desc' => 'Enter a brief description of the changes you\'ve made', + 'pages_edit_enter_changelog' => 'Enter Changelog', + 'pages_save' => 'Save Page', + 'pages_title' => 'Page Title', + 'pages_name' => 'Page Name', + 'pages_md_editor' => 'Editor', + 'pages_md_preview' => 'Preview', + 'pages_md_insert_image' => 'Insert Image', + 'pages_md_insert_link' => 'Insert Entity Link', + 'pages_md_insert_drawing' => 'Insert Drawing', + 'pages_not_in_chapter' => 'Page is not in a chapter', + 'pages_move' => 'Move Page', + 'pages_move_success' => 'Page moved to ":parentName"', + 'pages_copy' => 'Copy Page', + 'pages_copy_desination' => 'Copy Destination', + 'pages_copy_success' => 'Page successfully copied', + 'pages_permissions' => 'Page Permissions', + 'pages_permissions_success' => 'Page permissions updated', + 'pages_revision' => 'Revision', + 'pages_revisions' => 'Page Revisions', + 'pages_revisions_named' => 'Page Revisions for :pageName', + 'pages_revision_named' => 'Page Revision for :pageName', + 'pages_revisions_created_by' => 'Created By', + 'pages_revisions_date' => 'Revision Date', + 'pages_revisions_number' => '#', + 'pages_revisions_numbered' => 'Revision #:id', + 'pages_revisions_numbered_changes' => 'Revision #:id Changes', + 'pages_revisions_changelog' => 'Changelog', + 'pages_revisions_changes' => 'Changes', + 'pages_revisions_current' => 'Current Version', + 'pages_revisions_preview' => 'Preview', + 'pages_revisions_restore' => 'Restore', + 'pages_revisions_none' => 'This page has no revisions', + 'pages_copy_link' => 'Copy Link', + 'pages_edit_content_link' => 'Edit Content', + 'pages_permissions_active' => 'Page Permissions Active', + 'pages_initial_revision' => 'Initial publish', + 'pages_initial_name' => 'New Page', + 'pages_editing_draft_notification' => 'You are currently editing a draft that was last saved :timeDiff.', + 'pages_draft_edited_notification' => 'This page has been updated by since that time. It is recommended that you discard this draft.', + 'pages_draft_edit_active' => [ + 'start_a' => ':count users have started editing this page', + 'start_b' => ':userName has started editing this page', + 'time_a' => 'since the page was last updated', + 'time_b' => 'in the last :minCount minutes', + 'message' => ':start :time. Take care not to overwrite each other\'s updates!', + ], + 'pages_draft_discarded' => 'Draft discarded, The editor has been updated with the current page content', + 'pages_specific' => 'Specific Page', + 'pages_is_template' => 'Page Template', + + // Editor Sidebar + 'page_tags' => 'Page Tags', + 'chapter_tags' => 'Chapter Tags', + 'book_tags' => 'Book Tags', + 'shelf_tags' => 'Shelf Tags', + 'tag' => 'Tag', + 'tags' => 'Tags', + 'tag_name' => 'Tag Name', + 'tag_value' => 'Tag Value (Optional)', + 'tags_explain' => "Add some tags to better categorise your content. \n You can assign a value to a tag for more in-depth organisation.", + 'tags_add' => 'Add another tag', + 'tags_remove' => 'Remove this tag', + 'attachments' => 'Attachments', + 'attachments_explain' => 'Upload some files or attach some links to display on your page. These are visible in the page sidebar.', + 'attachments_explain_instant_save' => 'Changes here are saved instantly.', + 'attachments_items' => 'Attached Items', + 'attachments_upload' => 'Upload File', + 'attachments_link' => 'Attach Link', + 'attachments_set_link' => 'Set Link', + 'attachments_delete_confirm' => 'Click delete again to confirm you want to delete this attachment.', + 'attachments_dropzone' => 'Drop files or click here to attach a file', + 'attachments_no_files' => 'No files have been uploaded', + 'attachments_explain_link' => 'You can attach a link if you\'d prefer not to upload a file. This can be a link to another page or a link to a file in the cloud.', + 'attachments_link_name' => 'Link Name', + 'attachment_link' => 'Attachment link', + 'attachments_link_url' => 'Link to file', + 'attachments_link_url_hint' => 'Url of site or file', + 'attach' => 'Attach', + 'attachments_edit_file' => 'Edit File', + 'attachments_edit_file_name' => 'File Name', + 'attachments_edit_drop_upload' => 'Drop files or click here to upload and overwrite', + 'attachments_order_updated' => 'Attachment order updated', + 'attachments_updated_success' => 'Attachment details updated', + 'attachments_deleted' => 'Attachment deleted', + 'attachments_file_uploaded' => 'File successfully uploaded', + 'attachments_file_updated' => 'File successfully updated', + 'attachments_link_attached' => 'Link successfully attached to page', + 'templates' => 'Templates', + 'templates_set_as_template' => 'Page is a template', + 'templates_explain_set_as_template' => 'You can set this page as a template so its contents be utilized when creating other pages. Other users will be able to use this template if they have view permissions for this page.', + 'templates_replace_content' => 'Replace page content', + 'templates_append_content' => 'Append to page content', + 'templates_prepend_content' => 'Prepend to page content', + + // Profile View + 'profile_user_for_x' => 'User for :time', + 'profile_created_content' => 'Created Content', + 'profile_not_created_pages' => ':userName has not created any pages', + 'profile_not_created_chapters' => ':userName has not created any chapters', + 'profile_not_created_books' => ':userName has not created any books', + 'profile_not_created_shelves' => ':userName has not created any shelves', + + // Comments + 'comment' => 'Comment', + 'comments' => 'Comments', + 'comment_add' => 'Add Comment', + 'comment_placeholder' => 'Leave a comment here', + 'comment_count' => '{0} No Comments|{1} 1 Comment|[2,*] :count Comments', + 'comment_save' => 'Save Comment', + 'comment_saving' => 'Saving comment...', + 'comment_deleting' => 'Deleting comment...', + 'comment_new' => 'New Comment', + 'comment_created' => 'commented :createDiff', + 'comment_updated' => 'Updated :updateDiff by :username', + 'comment_deleted_success' => 'Comment deleted', + 'comment_created_success' => 'Comment added', + 'comment_updated_success' => 'Comment updated', + 'comment_delete_confirm' => 'Are you sure you want to delete this comment?', + 'comment_in_reply_to' => 'In reply to :commentId', + + // Revision + 'revision_delete_confirm' => 'Are you sure you want to delete this revision?', + 'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.', + 'revision_delete_success' => 'Revision deleted', + 'revision_cannot_delete_latest' => 'Cannot delete the latest revision.' +]; \ No newline at end of file diff --git a/resources/lang/th/errors.php b/resources/lang/th/errors.php new file mode 100644 index 000000000..06a5285f5 --- /dev/null +++ b/resources/lang/th/errors.php @@ -0,0 +1,103 @@ + 'You do not have permission to access the requested page.', + 'permissionJson' => 'You do not have permission to perform the requested action.', + + // Auth + 'error_user_exists_different_creds' => 'A user with the email :email already exists but with different credentials.', + 'email_already_confirmed' => 'Email has already been confirmed, Try logging in.', + 'email_confirmation_invalid' => 'This confirmation token is not valid or has already been used, Please try registering again.', + 'email_confirmation_expired' => 'The confirmation token has expired, A new confirmation email has been sent.', + 'email_confirmation_awaiting' => 'The email address for the account in use needs to be confirmed', + 'ldap_fail_anonymous' => 'LDAP access failed using anonymous bind', + 'ldap_fail_authed' => 'LDAP access failed using given dn & password details', + 'ldap_extension_not_installed' => 'LDAP PHP extension not installed', + 'ldap_cannot_connect' => 'Cannot connect to ldap server, Initial connection failed', + 'saml_already_logged_in' => 'Already logged in', + 'saml_user_not_registered' => 'The user :name is not registered and automatic registration is disabled', + 'saml_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system', + 'saml_invalid_response_id' => 'The request from the external authentication system is not recognised by a process started by this application. Navigating back after a login could cause this issue.', + 'saml_fail_authed' => 'Login using :system failed, system did not provide successful authorization', + 'social_no_action_defined' => 'No action defined', + 'social_login_bad_response' => "Error received during :socialAccount login: \n:error", + 'social_account_in_use' => 'This :socialAccount account is already in use, Try logging in via the :socialAccount option.', + 'social_account_email_in_use' => 'The email :email is already in use. If you already have an account you can connect your :socialAccount account from your profile settings.', + 'social_account_existing' => 'This :socialAccount is already attached to your profile.', + 'social_account_already_used_existing' => 'This :socialAccount account is already used by another user.', + 'social_account_not_used' => 'This :socialAccount account is not linked to any users. Please attach it in your profile settings. ', + 'social_account_register_instructions' => 'If you do not yet have an account, You can register an account using the :socialAccount option.', + 'social_driver_not_found' => 'Social driver not found', + 'social_driver_not_configured' => 'Your :socialAccount social settings are not configured correctly.', + 'invite_token_expired' => 'This invitation link has expired. You can instead try to reset your account password.', + + // System + 'path_not_writable' => 'File path :filePath could not be uploaded to. Ensure it is writable to the server.', + 'cannot_get_image_from_url' => 'Cannot get image from :url', + 'cannot_create_thumbs' => 'The server cannot create thumbnails. Please check you have the GD PHP extension installed.', + 'server_upload_limit' => 'The server does not allow uploads of this size. Please try a smaller file size.', + 'uploaded' => 'The server does not allow uploads of this size. Please try a smaller file size.', + 'image_upload_error' => 'An error occurred uploading the image', + 'image_upload_type_error' => 'The image type being uploaded is invalid', + 'file_upload_timeout' => 'The file upload has timed out.', + + // Attachments + 'attachment_page_mismatch' => 'Page mismatch during attachment update', + 'attachment_not_found' => 'Attachment not found', + + // Pages + 'page_draft_autosave_fail' => 'Failed to save draft. Ensure you have internet connection before saving this page', + 'page_custom_home_deletion' => 'Cannot delete a page while it is set as a homepage', + + // Entities + 'entity_not_found' => 'Entity not found', + 'bookshelf_not_found' => 'Bookshelf not found', + 'book_not_found' => 'Book not found', + 'page_not_found' => 'Page not found', + 'chapter_not_found' => 'Chapter not found', + 'selected_book_not_found' => 'The selected book was not found', + 'selected_book_chapter_not_found' => 'The selected Book or Chapter was not found', + 'guests_cannot_save_drafts' => 'Guests cannot save drafts', + + // Users + 'users_cannot_delete_only_admin' => 'You cannot delete the only admin', + 'users_cannot_delete_guest' => 'You cannot delete the guest user', + + // Roles + 'role_cannot_be_edited' => 'This role cannot be edited', + 'role_system_cannot_be_deleted' => 'This role is a system role and cannot be deleted', + 'role_registration_default_cannot_delete' => 'This role cannot be deleted while set as the default registration role', + 'role_cannot_remove_only_admin' => 'This user is the only user assigned to the administrator role. Assign the administrator role to another user before attempting to remove it here.', + + // Comments + 'comment_list' => 'An error occurred while fetching the comments.', + 'cannot_add_comment_to_draft' => 'You cannot add comments to a draft.', + 'comment_add' => 'An error occurred while adding / updating the comment.', + 'comment_delete' => 'An error occurred while deleting the comment.', + 'empty_comment' => 'Cannot add an empty comment.', + + // Error pages + '404_page_not_found' => 'Page Not Found', + 'sorry_page_not_found' => 'Sorry, The page you were looking for could not be found.', + 'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.', + 'return_home' => 'Return to home', + 'error_occurred' => 'An Error Occurred', + 'app_down' => ':appName is down right now', + 'back_soon' => 'It will be back up soon.', + + // API errors + 'api_no_authorization_found' => 'No authorization token found on the request', + 'api_bad_authorization_format' => 'An authorization token was found on the request but the format appeared incorrect', + 'api_user_token_not_found' => 'No matching API token was found for the provided authorization token', + 'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect', + 'api_user_no_api_permission' => 'The owner of the used API token does not have permission to make API calls', + 'api_user_token_expired' => 'The authorization token used has expired', + + // Settings & Maintenance + 'maintenance_test_email_failure' => 'Error thrown when sending a test email:', + +]; diff --git a/resources/lang/th/pagination.php b/resources/lang/th/pagination.php new file mode 100644 index 000000000..85bd12fc3 --- /dev/null +++ b/resources/lang/th/pagination.php @@ -0,0 +1,12 @@ + '« Previous', + 'next' => 'Next »', + +]; diff --git a/resources/lang/th/passwords.php b/resources/lang/th/passwords.php new file mode 100644 index 000000000..b408f3c2f --- /dev/null +++ b/resources/lang/th/passwords.php @@ -0,0 +1,15 @@ + 'Passwords must be at least eight characters and match the confirmation.', + 'user' => "We can't find a user with that e-mail address.", + 'token' => 'The password reset token is invalid for this email address.', + 'sent' => 'We have e-mailed your password reset link!', + 'reset' => 'Your password has been reset!', + +]; diff --git a/resources/lang/th/settings.php b/resources/lang/th/settings.php new file mode 100644 index 000000000..f1345c743 --- /dev/null +++ b/resources/lang/th/settings.php @@ -0,0 +1,214 @@ + 'Settings', + 'settings_save' => 'Save Settings', + 'settings_save_success' => 'Settings saved', + + // App Settings + 'app_customization' => 'Customization', + 'app_features_security' => 'Features & Security', + 'app_name' => 'Application Name', + 'app_name_desc' => 'This name is shown in the header and in any system-sent emails.', + 'app_name_header' => 'Show name in header', + 'app_public_access' => 'Public Access', + 'app_public_access_desc' => 'Enabling this option will allow visitors, that are not logged-in, to access content in your BookStack instance.', + 'app_public_access_desc_guest' => 'Access for public visitors can be controlled through the "Guest" user.', + 'app_public_access_toggle' => 'Allow public access', + 'app_public_viewing' => 'Allow public viewing?', + 'app_secure_images' => 'Higher Security Image Uploads', + 'app_secure_images_toggle' => 'Enable higher security image uploads', + 'app_secure_images_desc' => 'For performance reasons, all images are public. This option adds a random, hard-to-guess string in front of image urls. Ensure directory indexes are not enabled to prevent easy access.', + 'app_editor' => 'Page Editor', + 'app_editor_desc' => 'Select which editor will be used by all users to edit pages.', + 'app_custom_html' => 'Custom HTML Head Content', + 'app_custom_html_desc' => 'Any content added here will be inserted into the bottom of the section of every page. This is handy for overriding styles or adding analytics code.', + 'app_custom_html_disabled_notice' => 'Custom HTML head content is disabled on this settings page to ensure any breaking changes can be reverted.', + 'app_logo' => 'Application Logo', + 'app_logo_desc' => 'This image should be 43px in height.
    Large images will be scaled down.', + 'app_primary_color' => 'Application Primary Color', + 'app_primary_color_desc' => 'Sets the primary color for the application including the banner, buttons, and links.', + 'app_homepage' => 'Application Homepage', + 'app_homepage_desc' => 'Select a view to show on the homepage instead of the default view. Page permissions are ignored for selected pages.', + 'app_homepage_select' => 'Select a page', + 'app_disable_comments' => 'Disable Comments', + 'app_disable_comments_toggle' => 'Disable comments', + 'app_disable_comments_desc' => 'Disables comments across all pages in the application.
    Existing comments are not shown.', + + // Color settings + 'content_colors' => 'Content Colors', + 'content_colors_desc' => 'Sets colors for all elements in the page organisation hierarchy. Choosing colors with a similar brightness to the default colors is recommended for readability.', + 'bookshelf_color' => 'Shelf Color', + 'book_color' => 'Book Color', + 'chapter_color' => 'Chapter Color', + 'page_color' => 'Page Color', + 'page_draft_color' => 'Page Draft Color', + + // Registration Settings + 'reg_settings' => 'Registration', + 'reg_enable' => 'Enable Registration', + 'reg_enable_toggle' => 'Enable registration', + 'reg_enable_desc' => 'When registration is enabled user will be able to sign themselves up as an application user. Upon registration they are given a single, default user role.', + 'reg_default_role' => 'Default user role after registration', + 'reg_enable_external_warning' => 'The option above is ignored while external LDAP or SAML authentication is active. User accounts for non-existing members will be auto-created if authentication, against the external system in use, is successful.', + 'reg_email_confirmation' => 'Email Confirmation', + 'reg_email_confirmation_toggle' => 'Require email confirmation', + 'reg_confirm_email_desc' => 'If domain restriction is used then email confirmation will be required and this option will be ignored.', + 'reg_confirm_restrict_domain' => 'Domain Restriction', + 'reg_confirm_restrict_domain_desc' => 'Enter a comma separated list of email domains you would like to restrict registration to. Users will be sent an email to confirm their address before being allowed to interact with the application.
    Note that users will be able to change their email addresses after successful registration.', + 'reg_confirm_restrict_domain_placeholder' => 'No restriction set', + + // Maintenance settings + 'maint' => 'Maintenance', + 'maint_image_cleanup' => 'Cleanup Images', + 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.", + 'maint_image_cleanup_ignore_revisions' => 'Ignore images in revisions', + 'maint_image_cleanup_run' => 'Run Cleanup', + 'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?', + 'maint_image_cleanup_success' => ':count potentially unused images found and deleted!', + 'maint_image_cleanup_nothing_found' => 'No unused images found, Nothing deleted!', + 'maint_send_test_email' => 'Send a Test Email', + 'maint_send_test_email_desc' => 'This sends a test email to your email address specified in your profile.', + 'maint_send_test_email_run' => 'Send test email', + 'maint_send_test_email_success' => 'Email sent to :address', + 'maint_send_test_email_mail_subject' => 'Test Email', + 'maint_send_test_email_mail_greeting' => 'Email delivery seems to work!', + 'maint_send_test_email_mail_text' => 'Congratulations! As you received this email notification, your email settings seem to be configured properly.', + + // Role Settings + 'roles' => 'Roles', + 'role_user_roles' => 'User Roles', + 'role_create' => 'Create New Role', + 'role_create_success' => 'Role successfully created', + 'role_delete' => 'Delete Role', + 'role_delete_confirm' => 'This will delete the role with the name \':roleName\'.', + 'role_delete_users_assigned' => 'This role has :userCount users assigned to it. If you would like to migrate the users from this role select a new role below.', + 'role_delete_no_migration' => "Don't migrate users", + 'role_delete_sure' => 'Are you sure you want to delete this role?', + 'role_delete_success' => 'Role successfully deleted', + 'role_edit' => 'Edit Role', + 'role_details' => 'Role Details', + 'role_name' => 'Role Name', + 'role_desc' => 'Short Description of Role', + 'role_external_auth_id' => 'External Authentication IDs', + 'role_system' => 'System Permissions', + 'role_manage_users' => 'Manage users', + 'role_manage_roles' => 'Manage roles & role permissions', + 'role_manage_entity_permissions' => 'Manage all book, chapter & page permissions', + 'role_manage_own_entity_permissions' => 'Manage permissions on own book, chapter & pages', + 'role_manage_page_templates' => 'Manage page templates', + 'role_access_api' => 'Access system API', + 'role_manage_settings' => 'Manage app settings', + 'role_asset' => 'Asset Permissions', + 'role_asset_desc' => 'These permissions control default access to the assets within the system. Permissions on Books, Chapters and Pages will override these permissions.', + 'role_asset_admins' => 'Admins are automatically given access to all content but these options may show or hide UI options.', + 'role_all' => 'All', + 'role_own' => 'Own', + 'role_controlled_by_asset' => 'Controlled by the asset they are uploaded to', + 'role_save' => 'Save Role', + 'role_update_success' => 'Role successfully updated', + 'role_users' => 'Users in this role', + 'role_users_none' => 'No users are currently assigned to this role', + + // Users + 'users' => 'Users', + 'user_profile' => 'User Profile', + 'users_add_new' => 'Add New User', + 'users_search' => 'Search Users', + 'users_details' => 'User Details', + 'users_details_desc' => 'Set a display name and an email address for this user. The email address will be used for logging into the application.', + 'users_details_desc_no_email' => 'Set a display name for this user so others can recognise them.', + 'users_role' => 'User Roles', + 'users_role_desc' => 'Select which roles this user will be assigned to. If a user is assigned to multiple roles the permissions from those roles will stack and they will receive all abilities of the assigned roles.', + 'users_password' => 'User Password', + 'users_password_desc' => 'Set a password used to log-in to the application. This must be at least 6 characters long.', + 'users_send_invite_text' => 'You can choose to send this user an invitation email which allows them to set their own password otherwise you can set their password yourself.', + 'users_send_invite_option' => 'Send user invite email', + 'users_external_auth_id' => 'External Authentication ID', + 'users_external_auth_id_desc' => 'This is the ID used to match this user when communicating with your external authentication system.', + 'users_password_warning' => 'Only fill the below if you would like to change your password.', + 'users_system_public' => 'This user represents any guest users that visit your instance. It cannot be used to log in but is assigned automatically.', + 'users_delete' => 'Delete User', + 'users_delete_named' => 'Delete user :userName', + 'users_delete_warning' => 'This will fully delete this user with the name \':userName\' from the system.', + 'users_delete_confirm' => 'Are you sure you want to delete this user?', + 'users_delete_success' => 'Users successfully removed', + 'users_edit' => 'Edit User', + 'users_edit_profile' => 'Edit Profile', + 'users_edit_success' => 'User successfully updated', + 'users_avatar' => 'User Avatar', + 'users_avatar_desc' => 'Select an image to represent this user. This should be approx 256px square.', + 'users_preferred_language' => 'Preferred Language', + 'users_preferred_language_desc' => 'This option will change the language used for the user-interface of the application. This will not affect any user-created content.', + 'users_social_accounts' => 'Social Accounts', + 'users_social_accounts_info' => 'Here you can connect your other accounts for quicker and easier login. Disconnecting an account here does not revoke previously authorized access. Revoke access from your profile settings on the connected social account.', + 'users_social_connect' => 'Connect Account', + 'users_social_disconnect' => 'Disconnect Account', + 'users_social_connected' => ':socialAccount account was successfully attached to your profile.', + 'users_social_disconnected' => ':socialAccount account was successfully disconnected from your profile.', + 'users_api_tokens' => 'API Tokens', + 'users_api_tokens_none' => 'No API tokens have been created for this user', + 'users_api_tokens_create' => 'Create Token', + 'users_api_tokens_expires' => 'Expires', + 'users_api_tokens_docs' => 'API Documentation', + + // API Tokens + 'user_api_token_create' => 'Create API Token', + 'user_api_token_name' => 'Name', + 'user_api_token_name_desc' => 'Give your token a readable name as a future reminder of its intended purpose.', + 'user_api_token_expiry' => 'Expiry Date', + 'user_api_token_expiry_desc' => 'Set a date at which this token expires. After this date, requests made using this token will no longer work. Leaving this field blank will set an expiry 100 years into the future.', + 'user_api_token_create_secret_message' => 'Immediately after creating this token a "Token ID"" & "Token Secret" will be generated and displayed. The secret will only be shown a single time so be sure to copy the value to somewhere safe and secure before proceeding.', + 'user_api_token_create_success' => 'API token successfully created', + 'user_api_token_update_success' => 'API token successfully updated', + 'user_api_token' => 'API Token', + 'user_api_token_id' => 'Token ID', + 'user_api_token_id_desc' => 'This is a non-editable system generated identifier for this token which will need to be provided in API requests.', + 'user_api_token_secret' => 'Token Secret', + 'user_api_token_secret_desc' => 'This is a system generated secret for this token which will need to be provided in API requests. This will only be displayed this one time so copy this value to somewhere safe and secure.', + 'user_api_token_created' => 'Token Created :timeAgo', + 'user_api_token_updated' => 'Token Updated :timeAgo', + 'user_api_token_delete' => 'Delete Token', + 'user_api_token_delete_warning' => 'This will fully delete this API token with the name \':tokenName\' from the system.', + 'user_api_token_delete_confirm' => 'Are you sure you want to delete this API token?', + 'user_api_token_delete_success' => 'API token successfully deleted', + + //! If editing translations files directly please ignore this in all + //! languages apart from en. Content will be auto-copied from en. + //!//////////////////////////////// + 'language_select' => [ + 'en' => 'English', + 'ar' => 'العربية', + 'cs' => 'Česky', + 'da' => 'Dansk', + 'de' => 'Deutsch (Sie)', + 'de_informal' => 'Deutsch (Du)', + 'es' => 'Español', + 'es_AR' => 'Español Argentina', + 'fr' => 'Français', + 'he' => 'עברית', + 'hu' => 'Magyar', + 'it' => 'Italian', + 'ja' => '日本語', + 'ko' => '한국어', + 'nl' => 'Nederlands', + 'pl' => 'Polski', + 'pt_BR' => 'Português do Brasil', + 'ru' => 'Русский', + 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', + 'sv' => 'Svenska', + 'tr' => 'Türkçe', + 'uk' => 'Українська', + 'vi' => 'Tiếng Việt', + 'zh_CN' => '简体中文', + 'zh_TW' => '繁體中文', + ] + //!//////////////////////////////// +]; diff --git a/resources/lang/th/validation.php b/resources/lang/th/validation.php new file mode 100644 index 000000000..76b57a2a3 --- /dev/null +++ b/resources/lang/th/validation.php @@ -0,0 +1,114 @@ + 'The :attribute must be accepted.', + 'active_url' => 'The :attribute is not a valid URL.', + 'after' => 'The :attribute must be a date after :date.', + 'alpha' => 'The :attribute may only contain letters.', + 'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.', + 'alpha_num' => 'The :attribute may only contain letters and numbers.', + 'array' => 'The :attribute must be an array.', + 'before' => 'The :attribute must be a date before :date.', + 'between' => [ + 'numeric' => 'The :attribute must be between :min and :max.', + 'file' => 'The :attribute must be between :min and :max kilobytes.', + 'string' => 'The :attribute must be between :min and :max characters.', + 'array' => 'The :attribute must have between :min and :max items.', + ], + 'boolean' => 'The :attribute field must be true or false.', + 'confirmed' => 'The :attribute confirmation does not match.', + 'date' => 'The :attribute is not a valid date.', + 'date_format' => 'The :attribute does not match the format :format.', + 'different' => 'The :attribute and :other must be different.', + 'digits' => 'The :attribute must be :digits digits.', + 'digits_between' => 'The :attribute must be between :min and :max digits.', + 'email' => 'The :attribute must be a valid email address.', + 'ends_with' => 'The :attribute must end with one of the following: :values', + 'filled' => 'The :attribute field is required.', + 'gt' => [ + 'numeric' => 'The :attribute must be greater than :value.', + 'file' => 'The :attribute must be greater than :value kilobytes.', + 'string' => 'The :attribute must be greater than :value characters.', + 'array' => 'The :attribute must have more than :value items.', + ], + 'gte' => [ + 'numeric' => 'The :attribute must be greater than or equal :value.', + 'file' => 'The :attribute must be greater than or equal :value kilobytes.', + 'string' => 'The :attribute must be greater than or equal :value characters.', + 'array' => 'The :attribute must have :value items or more.', + ], + 'exists' => 'The selected :attribute is invalid.', + 'image' => 'The :attribute must be an image.', + 'image_extension' => 'The :attribute must have a valid & supported image extension.', + 'in' => 'The selected :attribute is invalid.', + 'integer' => 'The :attribute must be an integer.', + 'ip' => 'The :attribute must be a valid IP address.', + 'ipv4' => 'The :attribute must be a valid IPv4 address.', + 'ipv6' => 'The :attribute must be a valid IPv6 address.', + 'json' => 'The :attribute must be a valid JSON string.', + 'lt' => [ + 'numeric' => 'The :attribute must be less than :value.', + 'file' => 'The :attribute must be less than :value kilobytes.', + 'string' => 'The :attribute must be less than :value characters.', + 'array' => 'The :attribute must have less than :value items.', + ], + 'lte' => [ + 'numeric' => 'The :attribute must be less than or equal :value.', + 'file' => 'The :attribute must be less than or equal :value kilobytes.', + 'string' => 'The :attribute must be less than or equal :value characters.', + 'array' => 'The :attribute must not have more than :value items.', + ], + 'max' => [ + 'numeric' => 'The :attribute may not be greater than :max.', + 'file' => 'The :attribute may not be greater than :max kilobytes.', + 'string' => 'The :attribute may not be greater than :max characters.', + 'array' => 'The :attribute may not have more than :max items.', + ], + 'mimes' => 'The :attribute must be a file of type: :values.', + 'min' => [ + 'numeric' => 'The :attribute must be at least :min.', + 'file' => 'The :attribute must be at least :min kilobytes.', + 'string' => 'The :attribute must be at least :min characters.', + 'array' => 'The :attribute must have at least :min items.', + ], + 'no_double_extension' => 'The :attribute must only have a single file extension.', + 'not_in' => 'The selected :attribute is invalid.', + 'not_regex' => 'The :attribute format is invalid.', + 'numeric' => 'The :attribute must be a number.', + 'regex' => 'The :attribute format is invalid.', + 'required' => 'The :attribute field is required.', + 'required_if' => 'The :attribute field is required when :other is :value.', + 'required_with' => 'The :attribute field is required when :values is present.', + 'required_with_all' => 'The :attribute field is required when :values is present.', + 'required_without' => 'The :attribute field is required when :values is not present.', + 'required_without_all' => 'The :attribute field is required when none of :values are present.', + 'same' => 'The :attribute and :other must match.', + 'size' => [ + 'numeric' => 'The :attribute must be :size.', + 'file' => 'The :attribute must be :size kilobytes.', + 'string' => 'The :attribute must be :size characters.', + 'array' => 'The :attribute must contain :size items.', + ], + 'string' => 'The :attribute must be a string.', + 'timezone' => 'The :attribute must be a valid zone.', + 'unique' => 'The :attribute has already been taken.', + 'url' => 'The :attribute format is invalid.', + 'uploaded' => 'The file could not be uploaded. The server may not accept files of this size.', + + // Custom validation lines + 'custom' => [ + 'password-confirm' => [ + 'required_with' => 'Password confirmation required', + ], + ], + + // Custom validation attributes + 'attributes' => [], +]; diff --git a/resources/lang/tr/common.php b/resources/lang/tr/common.php index ae9bfe847..587640672 100644 --- a/resources/lang/tr/common.php +++ b/resources/lang/tr/common.php @@ -66,8 +66,8 @@ return [ 'profile_menu' => 'Profil Menüsü', 'view_profile' => 'Profili Görüntüle', 'edit_profile' => 'Profili Düzenle', - 'dark_mode' => 'Dark Mode', - 'light_mode' => 'Light Mode', + 'dark_mode' => 'Gece Modu', + 'light_mode' => 'Aydınlık Modu', // Layout tabs 'tab_info' => 'Bilgi', diff --git a/resources/lang/zh_CN/settings.php b/resources/lang/zh_CN/settings.php index 1c2a0aa18..c2f015533 100755 --- a/resources/lang/zh_CN/settings.php +++ b/resources/lang/zh_CN/settings.php @@ -57,9 +57,9 @@ return [ 'reg_enable_desc' => '启用注册后,用户将可以自己注册为站点用户。 注册后,他们将获得一个默认的单一用户角色。', 'reg_default_role' => '注册后的默认用户角色', 'reg_enable_external_warning' => '当启用外部LDAP或者SAML认证时,上面的选项会被忽略。当使用外部系统认证认证成功时,将自动创建非现有会员的用户账户。', - 'reg_email_confirmation' => '电子邮件确认', - 'reg_email_confirmation_toggle' => '新用户注册时,需要电子邮件确认', - 'reg_confirm_email_desc' => '如果启用域名限制功能,则自动开启电子邮件确认,并且本项设定将被忽略。', + 'reg_email_confirmation' => '邮箱确认n', + 'reg_email_confirmation_toggle' => '需要电子邮件确认', + 'reg_confirm_email_desc' => '如果使用域名限制,则需要Email验证,并且该值将被忽略。', 'reg_confirm_restrict_domain' => '域名限制', 'reg_confirm_restrict_domain_desc' => '输入您想要限制注册的Email域名列表,用逗号隔开。在被允许与应用程序交互之前,用户将被发送一封Email来确认他们的地址。
    注意用户在注册成功后可以修改他们的Email地址。', 'reg_confirm_restrict_domain_placeholder' => '尚未设置限制', From ce8cea6a9f84a15ac2043661be0714ae755dea82 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 28 Apr 2020 12:25:15 +0100 Subject: [PATCH 049/197] New Crowdin translations (#2071) * New translations common.php (Korean) * New translations settings.php (Korean) --- resources/lang/ko/common.php | 4 ++-- resources/lang/ko/settings.php | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/resources/lang/ko/common.php b/resources/lang/ko/common.php index 56fc323f9..67cc87bd2 100644 --- a/resources/lang/ko/common.php +++ b/resources/lang/ko/common.php @@ -66,8 +66,8 @@ return [ 'profile_menu' => '프로필', 'view_profile' => '프로필 보기', 'edit_profile' => '프로필 바꾸기', - 'dark_mode' => 'Dark Mode', - 'light_mode' => 'Light Mode', + 'dark_mode' => '다크 모드', + 'light_mode' => '라이트 모드', // Layout tabs 'tab_info' => '정보', diff --git a/resources/lang/ko/settings.php b/resources/lang/ko/settings.php index 4bf653f6c..e7cec851a 100755 --- a/resources/lang/ko/settings.php +++ b/resources/lang/ko/settings.php @@ -103,7 +103,7 @@ return [ 'role_manage_entity_permissions' => '문서별 권한 관리', 'role_manage_own_entity_permissions' => '직접 만든 문서별 권한 관리', 'role_manage_page_templates' => '템플릿 관리', - 'role_access_api' => 'Access system API', + 'role_access_api' => '시스템 접근 API', 'role_manage_settings' => '사이트 설정 관리', 'role_asset' => '권한 항목', 'role_asset_desc' => '책자, 챕터, 문서별 권한은 이 설정에 우선합니다.', @@ -152,29 +152,29 @@ return [ 'users_social_disconnect' => '계정 연결 끊기', 'users_social_connected' => ':socialAccount(와)과 연결했습니다.', 'users_social_disconnected' => ':socialAccount(와)과의 연결을 끊었습니다.', - 'users_api_tokens' => 'API Tokens', + 'users_api_tokens' => 'API 토큰', 'users_api_tokens_none' => 'No API tokens have been created for this user', - 'users_api_tokens_create' => 'Create Token', - 'users_api_tokens_expires' => 'Expires', - 'users_api_tokens_docs' => 'API Documentation', + 'users_api_tokens_create' => '토큰 만들기', + 'users_api_tokens_expires' => '만료', + 'users_api_tokens_docs' => 'API 설명서', // API Tokens - 'user_api_token_create' => 'Create API Token', - 'user_api_token_name' => 'Name', + 'user_api_token_create' => 'API 토큰 만들기', + 'user_api_token_name' => '제목', 'user_api_token_name_desc' => 'Give your token a readable name as a future reminder of its intended purpose.', - 'user_api_token_expiry' => 'Expiry Date', + 'user_api_token_expiry' => '만료일', 'user_api_token_expiry_desc' => 'Set a date at which this token expires. After this date, requests made using this token will no longer work. Leaving this field blank will set an expiry 100 years into the future.', 'user_api_token_create_secret_message' => 'Immediately after creating this token a "Token ID"" & "Token Secret" will be generated and displayed. The secret will only be shown a single time so be sure to copy the value to somewhere safe and secure before proceeding.', 'user_api_token_create_success' => 'API token successfully created', 'user_api_token_update_success' => 'API token successfully updated', - 'user_api_token' => 'API Token', - 'user_api_token_id' => 'Token ID', + 'user_api_token' => 'API 토큰', + 'user_api_token_id' => '토큰 ID', 'user_api_token_id_desc' => 'This is a non-editable system generated identifier for this token which will need to be provided in API requests.', 'user_api_token_secret' => 'Token Secret', 'user_api_token_secret_desc' => 'This is a system generated secret for this token which will need to be provided in API requests. This will only be displayed this one time so copy this value to somewhere safe and secure.', 'user_api_token_created' => 'Token Created :timeAgo', 'user_api_token_updated' => 'Token Updated :timeAgo', - 'user_api_token_delete' => 'Delete Token', + 'user_api_token_delete' => '토큰 삭제', 'user_api_token_delete_warning' => 'This will fully delete this API token with the name \':tokenName\' from the system.', 'user_api_token_delete_confirm' => 'Are you sure you want to delete this API token?', 'user_api_token_delete_success' => 'API token successfully deleted', From 00c77e494bf8336f052a10daad5a59265198cf7d Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 28 Apr 2020 12:28:19 +0100 Subject: [PATCH 050/197] Updated ci with php7.4, update locale array --- .github/workflows/phpunit.yml | 2 +- app/Config/app.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index fa2437f37..7646f0687 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: [7.2, 7.3] + php: [7.2, 7.4] steps: - uses: actions/checkout@v1 diff --git a/app/Config/app.php b/app/Config/app.php index cf34fd694..a9956edd8 100755 --- a/app/Config/app.php +++ b/app/Config/app.php @@ -52,7 +52,7 @@ return [ 'locale' => env('APP_LANG', 'en'), // Locales available - 'locales' => ['en', 'ar', 'cs', 'da', 'de', 'de_informal', 'es', 'es_AR', 'fa', 'fr', 'he', 'hu', 'it', 'ja', 'ko', 'nl', 'pt', 'pt_BR', 'sk', 'sl', 'sv', 'pl', 'ru', 'tr', 'uk', 'vi', 'zh_CN', 'zh_TW',], + 'locales' => ['en', 'ar', 'cs', 'da', 'de', 'de_informal', 'es', 'es_AR', 'fa', 'fr', 'he', 'hu', 'it', 'ja', 'ko', 'nl', 'pt', 'pt_BR', 'sk', 'sl', 'sv', 'pl', 'ru', 'th', 'tr', 'uk', 'vi', 'zh_CN', 'zh_TW',], // Application Fallback Locale 'fallback_locale' => 'en', From dfceab7cfa0aaf68d6b155891d4096307f1876ed Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 28 Apr 2020 12:30:02 +0100 Subject: [PATCH 051/197] Updated translator attribution before release v0.29.1 --- .github/translators.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/translators.txt b/.github/translators.txt index ca8f0e218..098751fcd 100644 --- a/.github/translators.txt +++ b/.github/translators.txt @@ -95,3 +95,6 @@ Biepa :: German Informal; German syecu :: Chinese Simplified Lap1t0r :: French Thinkverse (thinkverse) :: Swedish +alef (toishoki) :: Turkish +Robbert Feunekes (Muukuro) :: Dutch +seohyeon.joo :: Korean From 2a2d0aa15b99f4181dd25b203b5932d56d221982 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 29 Apr 2020 18:28:26 +0100 Subject: [PATCH 052/197] Fixed incorrect color code causing yellow/orange code blocks --- resources/sass/_text.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/sass/_text.scss b/resources/sass/_text.scss index a2a5281d9..116504199 100644 --- a/resources/sass/_text.scss +++ b/resources/sass/_text.scss @@ -234,7 +234,7 @@ blockquote { font-size: 0.84em; border: 1px solid #DDD; border-radius: 3px; - @include lightDark(background-color, #f8f8f8f, #2b2b2b); + @include lightDark(background-color, #f8f8f8, #2b2b2b); @include lightDark(border-color, #DDD, #444); } From 3c26e7b72758302016545eeb4f780833c9b550df Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 1 May 2020 23:24:11 +0100 Subject: [PATCH 053/197] Updated comment md rendering to be server-side --- app/Actions/Comment.php | 8 ++- app/Actions/CommentRepo.php | 63 +++++++++++----------- app/Http/Controllers/CommentController.php | 14 ++--- app/Ownable.php | 4 ++ composer.json | 7 +-- composer.lock | 43 ++++++++++++--- resources/js/components/page-comments.js | 23 ++++---- tests/Entity/CommentTest.php | 43 ++++++++++++++- 8 files changed, 138 insertions(+), 67 deletions(-) diff --git a/app/Actions/Comment.php b/app/Actions/Comment.php index f138ee4a1..655d45221 100644 --- a/app/Actions/Comment.php +++ b/app/Actions/Comment.php @@ -2,9 +2,15 @@ use BookStack\Ownable; +/** + * @property string text + * @property string html + * @property int|null parent_id + * @property int local_id + */ class Comment extends Ownable { - protected $fillable = ['text', 'html', 'parent_id']; + protected $fillable = ['text', 'parent_id']; protected $appends = ['created', 'updated']; /** diff --git a/app/Actions/CommentRepo.php b/app/Actions/CommentRepo.php index 5ff639e2e..0d8a12ce9 100644 --- a/app/Actions/CommentRepo.php +++ b/app/Actions/CommentRepo.php @@ -1,23 +1,20 @@ comment = $comment; @@ -25,65 +22,71 @@ class CommentRepo /** * Get a comment by ID. - * @param $id - * @return \BookStack\Actions\Comment|\Illuminate\Database\Eloquent\Model */ - public function getById($id) + public function getById(int $id): Comment { return $this->comment->newQuery()->findOrFail($id); } /** * Create a new comment on an entity. - * @param \BookStack\Entities\Entity $entity - * @param array $data - * @return \BookStack\Actions\Comment */ - public function create(Entity $entity, $data = []) + public function create(Entity $entity, string $text, ?int $parent_id): Comment { $userId = user()->id; - $comment = $this->comment->newInstance($data); + $comment = $this->comment->newInstance(); + + $comment->text = $text; + $comment->html = $this->commentToHtml($text); $comment->created_by = $userId; $comment->updated_by = $userId; $comment->local_id = $this->getNextLocalId($entity); + $comment->parent_id = $parent_id; + $entity->comments()->save($comment); return $comment; } /** * Update an existing comment. - * @param \BookStack\Actions\Comment $comment - * @param array $input - * @return mixed */ - public function update($comment, $input) + public function update(Comment $comment, string $text): Comment { $comment->updated_by = user()->id; - $comment->update($input); + $comment->text = $text; + $comment->html = $this->commentToHtml($text); + $comment->save(); return $comment; } /** * Delete a comment from the system. - * @param \BookStack\Actions\Comment $comment - * @return mixed */ - public function delete($comment) + public function delete(Comment $comment) { - return $comment->delete(); + $comment->delete(); + } + + /** + * Convert the given comment markdown text to HTML. + */ + protected function commentToHtml(string $commentText): string + { + $converter = new CommonMarkConverter([ + 'html_input' => 'strip', + 'max_nesting_level' => 10, + 'allow_unsafe_links' => false, + ]); + + return $converter->convertToHtml($commentText); } /** * Get the next local ID relative to the linked entity. - * @param \BookStack\Entities\Entity $entity - * @return int */ - protected function getNextLocalId(Entity $entity) + protected function getNextLocalId(Entity $entity): int { $comments = $entity->comments(false)->orderBy('local_id', 'desc')->first(); - if ($comments === null) { - return 1; - } - return $comments->local_id + 1; + return ($comments->local_id ?? 0) + 1; } } diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index 068358d72..4eb56a4b0 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -10,9 +10,6 @@ class CommentController extends Controller { protected $commentRepo; - /** - * CommentController constructor. - */ public function __construct(CommentRepo $commentRepo) { $this->commentRepo = $commentRepo; @@ -23,11 +20,11 @@ class CommentController extends Controller * Save a new comment for a Page * @throws ValidationException */ - public function savePageComment(Request $request, int $pageId, int $commentId = null) + public function savePageComment(Request $request, int $pageId) { $this->validate($request, [ 'text' => 'required|string', - 'html' => 'required|string', + 'parent_id' => 'nullable|integer', ]); $page = Page::visible()->find($pageId); @@ -35,8 +32,6 @@ class CommentController extends Controller return response('Not found', 404); } - $this->checkOwnablePermission('page-view', $page); - // Prevent adding comments to draft pages if ($page->draft) { return $this->jsonError(trans('errors.cannot_add_comment_to_draft'), 400); @@ -44,7 +39,7 @@ class CommentController extends Controller // Create a new comment. $this->checkPermission('comment-create-all'); - $comment = $this->commentRepo->create($page, $request->only(['html', 'text', 'parent_id'])); + $comment = $this->commentRepo->create($page, $request->get('text'), $request->get('parent_id')); Activity::add($page, 'commented_on', $page->book->id); return view('comments.comment', ['comment' => $comment]); } @@ -57,14 +52,13 @@ class CommentController extends Controller { $this->validate($request, [ 'text' => 'required|string', - 'html' => 'required|string', ]); $comment = $this->commentRepo->getById($commentId); $this->checkOwnablePermission('page-view', $comment->entity); $this->checkOwnablePermission('comment-update', $comment); - $comment = $this->commentRepo->update($comment, $request->only(['html', 'text'])); + $comment = $this->commentRepo->update($comment, $request->get('text')); return view('comments.comment', ['comment' => $comment]); } diff --git a/app/Ownable.php b/app/Ownable.php index e660a0500..bf24fad5d 100644 --- a/app/Ownable.php +++ b/app/Ownable.php @@ -2,6 +2,10 @@ use BookStack\Auth\User; +/** + * @property int created_by + * @property int updated_by + */ abstract class Ownable extends Model { /** diff --git a/composer.json b/composer.json index 6da651898..80e8b0a61 100644 --- a/composer.json +++ b/composer.json @@ -16,12 +16,15 @@ "barryvdh/laravel-dompdf": "^0.8.5", "barryvdh/laravel-snappy": "^0.4.5", "doctrine/dbal": "^2.9", + "facade/ignition": "^1.4", "fideloper/proxy": "^4.0", "gathercontent/htmldiff": "^0.2.1", "intervention/image": "^2.5", "laravel/framework": "^6.12", "laravel/socialite": "^4.3.2", + "league/commonmark": "^1.4", "league/flysystem-aws-s3-v3": "^1.0", + "nunomaduro/collision": "^3.0", "onelogin/php-saml": "^3.3", "predis/predis": "^1.1", "socialiteproviders/discord": "^2.0", @@ -29,9 +32,7 @@ "socialiteproviders/microsoft-azure": "^3.0", "socialiteproviders/okta": "^1.0", "socialiteproviders/slack": "^3.0", - "socialiteproviders/twitch": "^5.0", - "facade/ignition": "^1.4", - "nunomaduro/collision": "^3.0" + "socialiteproviders/twitch": "^5.0" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.2.8", diff --git a/composer.lock b/composer.lock index fd444ffa8..3ddd28e5a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7836017e48e93254d6ff924b07f84597", + "content-hash": "bbe47cff4f167fd6ce7047dff4602a78", "packages": [ { "name": "aws/aws-sdk-php", @@ -1775,16 +1775,16 @@ }, { "name": "league/commonmark", - "version": "1.3.2", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "75542a366ccbe1896ed79fcf3e8e68206d6c4257" + "reference": "9e780d972185e4f737a03bade0fd34a9e67bbf31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/75542a366ccbe1896ed79fcf3e8e68206d6c4257", - "reference": "75542a366ccbe1896ed79fcf3e8e68206d6c4257", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/9e780d972185e4f737a03bade0fd34a9e67bbf31", + "reference": "9e780d972185e4f737a03bade0fd34a9e67bbf31", "shasum": "" }, "require": { @@ -1802,7 +1802,7 @@ "github/gfm": "0.29.0", "michelf/php-markdown": "~1.4", "mikehaertl/php-shellcommand": "^1.4", - "phpstan/phpstan-shim": "^0.11.5", + "phpstan/phpstan": "^0.12", "phpunit/phpunit": "^7.5", "scrutinizer/ocular": "^1.5", "symfony/finder": "^4.2" @@ -1845,7 +1845,33 @@ "md", "parser" ], - "time": "2020-03-25T19:55:28+00:00" + "funding": [ + { + "url": "https://enjoy.gitstore.app/repositories/thephpleague/commonmark", + "type": "custom" + }, + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://www.patreon.com/colinodell", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2020-04-24T13:39:56+00:00" }, { "name": "league/flysystem", @@ -7716,5 +7742,6 @@ "platform-dev": [], "platform-overrides": { "php": "7.2.0" - } + }, + "plugin-api-version": "1.1.0" } diff --git a/resources/js/components/page-comments.js b/resources/js/components/page-comments.js index 5d8d16958..5d826cba1 100644 --- a/resources/js/components/page-comments.js +++ b/resources/js/components/page-comments.js @@ -1,8 +1,5 @@ -import MarkdownIt from "markdown-it"; import {scrollAndHighlightElement} from "../services/util"; -const md = new MarkdownIt({ html: false }); - class PageComments { constructor(elem) { @@ -68,12 +65,11 @@ class PageComments { let text = form.querySelector('textarea').value; let reqData = { text: text, - html: md.render(text), parent_id: this.parentId || null, }; this.showLoading(form); let commentId = this.editingComment.getAttribute('comment'); - window.$http.put(window.baseUrl(`/ajax/comment/${commentId}`), reqData).then(resp => { + window.$http.put(`/ajax/comment/${commentId}`, reqData).then(resp => { let newComment = document.createElement('div'); newComment.innerHTML = resp.data; this.editingComment.innerHTML = newComment.children[0].innerHTML; @@ -88,7 +84,7 @@ class PageComments { deleteComment(commentElem) { let id = commentElem.getAttribute('comment'); this.showLoading(commentElem.querySelector('[comment-content]')); - window.$http.delete(window.baseUrl(`/ajax/comment/${id}`)).then(resp => { + window.$http.delete(`/ajax/comment/${id}`).then(resp => { commentElem.parentNode.removeChild(commentElem); window.$events.emit('success', window.trans('entities.comment_deleted_success')); this.updateCount(); @@ -102,11 +98,10 @@ class PageComments { let text = this.formInput.value; let reqData = { text: text, - html: md.render(text), parent_id: this.parentId || null, }; this.showLoading(this.form); - window.$http.post(window.baseUrl(`/ajax/page/${this.pageId}/comment`), reqData).then(resp => { + window.$http.post(`/ajax/page/${this.pageId}/comment`, reqData).then(resp => { let newComment = document.createElement('div'); newComment.innerHTML = resp.data; let newElem = newComment.children[0]; @@ -171,17 +166,17 @@ class PageComments { } showLoading(formElem) { - let groups = formElem.querySelectorAll('.form-group'); - for (let i = 0, len = groups.length; i < len; i++) { - groups[i].style.display = 'none'; + const groups = formElem.querySelectorAll('.form-group'); + for (let group of groups) { + group.style.display = 'none'; } formElem.querySelector('.form-group.loading').style.display = 'block'; } hideLoading(formElem) { - let groups = formElem.querySelectorAll('.form-group'); - for (let i = 0, len = groups.length; i < len; i++) { - groups[i].style.display = 'block'; + const groups = formElem.querySelectorAll('.form-group'); + for (let group of groups) { + group.style.display = 'block'; } formElem.querySelector('.form-group.loading').style.display = 'none'; } diff --git a/tests/Entity/CommentTest.php b/tests/Entity/CommentTest.php index a2126407b..2562f7e7d 100644 --- a/tests/Entity/CommentTest.php +++ b/tests/Entity/CommentTest.php @@ -42,7 +42,6 @@ class CommentTest extends TestCase $newText = 'updated text content'; $resp = $this->putJson("/ajax/comment/$comment->id", [ 'text' => $newText, - 'html' => '

    '.$newText.'

    ', ]); $resp->assertStatus(200); @@ -72,4 +71,46 @@ class CommentTest extends TestCase 'id' => $comment->id ]); } + + public function test_comments_converts_markdown_input_to_html() + { + $page = Page::first(); + $this->asAdmin()->postJson("/ajax/page/$page->id/comment", [ + 'text' => '# My Title', + ]); + + $this->assertDatabaseHas('comments', [ + 'entity_id' => $page->id, + 'entity_type' => $page->getMorphClass(), + 'text' => '# My Title', + 'html' => "

    My Title

    \n", + ]); + + $pageView = $this->get($page->getUrl()); + $pageView->assertSee('

    My Title

    '); + } + + public function test_html_cannot_be_injected_via_comment_content() + { + $this->asAdmin(); + $page = Page::first(); + + $script = '\n\n# sometextinthecomment'; + $this->postJson("/ajax/page/$page->id/comment", [ + 'text' => $script, + ]); + + $pageView = $this->get($page->getUrl()); + $pageView->assertDontSee($script); + $pageView->assertSee('sometextinthecomment'); + + $comment = $page->comments()->first(); + $this->putJson("/ajax/comment/$comment->id", [ + 'text' => $script . 'updated', + ]); + + $pageView = $this->get($page->getUrl()); + $pageView->assertDontSee($script); + $pageView->assertSee('sometextinthecommentupdated'); + } } From 413cac23aee584b0831f3e3fba79e91ee6fac7cf Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 1 May 2020 23:41:47 +0100 Subject: [PATCH 054/197] Added command to regenerate comment content --- app/Actions/CommentRepo.php | 2 +- .../Commands/RegenerateCommentContent.php | 61 +++++++++++++++++++ .../Commands/RegeneratePermissions.php | 2 - tests/CommandsTest.php | 24 ++++++++ 4 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 app/Console/Commands/RegenerateCommentContent.php diff --git a/app/Actions/CommentRepo.php b/app/Actions/CommentRepo.php index 0d8a12ce9..4dfe3ddb6 100644 --- a/app/Actions/CommentRepo.php +++ b/app/Actions/CommentRepo.php @@ -70,7 +70,7 @@ class CommentRepo /** * Convert the given comment markdown text to HTML. */ - protected function commentToHtml(string $commentText): string + public function commentToHtml(string $commentText): string { $converter = new CommonMarkConverter([ 'html_input' => 'strip', diff --git a/app/Console/Commands/RegenerateCommentContent.php b/app/Console/Commands/RegenerateCommentContent.php new file mode 100644 index 000000000..587a5edb3 --- /dev/null +++ b/app/Console/Commands/RegenerateCommentContent.php @@ -0,0 +1,61 @@ +commentRepo = $commentRepo; + parent::__construct(); + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + $connection = \DB::getDefaultConnection(); + if ($this->option('database') !== null) { + \DB::setDefaultConnection($this->option('database')); + } + + Comment::query()->chunk(100, function ($comments) { + foreach ($comments as $comment) { + $comment->html = $this->commentRepo->commentToHtml($comment->text); + $comment->save(); + } + }); + + \DB::setDefaultConnection($connection); + $this->comment('Comment HTML content has been regenerated'); + } +} diff --git a/app/Console/Commands/RegeneratePermissions.php b/app/Console/Commands/RegeneratePermissions.php index 430b8fcb0..4fde08e6b 100644 --- a/app/Console/Commands/RegeneratePermissions.php +++ b/app/Console/Commands/RegeneratePermissions.php @@ -30,8 +30,6 @@ class RegeneratePermissions extends Command /** * Create a new command instance. - * - * @param \BookStack\Auth\\BookStack\Auth\Permissions\PermissionService $permissionService */ public function __construct(PermissionService $permissionService) { diff --git a/tests/CommandsTest.php b/tests/CommandsTest.php index e55b047d4..bfc0ac0eb 100644 --- a/tests/CommandsTest.php +++ b/tests/CommandsTest.php @@ -1,5 +1,7 @@ expectException(RuntimeException::class); $this->artisan('bookstack:update-url https://cats.example.com'); } + + public function test_regenerate_comment_content_command() + { + Comment::query()->forceCreate([ + 'html' => 'some_old_content', + 'text' => 'some_fresh_content', + ]); + + $this->assertDatabaseHas('comments', [ + 'html' => 'some_old_content', + ]); + + $exitCode = \Artisan::call('bookstack:regenerate-comment-content'); + $this->assertTrue($exitCode === 0, 'Command executed successfully'); + + $this->assertDatabaseMissing('comments', [ + 'html' => 'some_old_content', + ]); + $this->assertDatabaseHas('comments', [ + 'html' => "

    some_fresh_content

    \n", + ]); + } } From d3ec38bee3eb1749b29726cb837a16efbec589da Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 2 May 2020 01:07:30 +0100 Subject: [PATCH 055/197] Removed unused function in registration service --- app/Auth/Access/RegistrationService.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/Auth/Access/RegistrationService.php b/app/Auth/Access/RegistrationService.php index 8cf76013a..9136b37b5 100644 --- a/app/Auth/Access/RegistrationService.php +++ b/app/Auth/Access/RegistrationService.php @@ -106,13 +106,4 @@ class RegistrationService } } - /** - * Alias to the UserRepo method of the same name. - * Attaches the default system role, if configured, to the given user. - */ - public function attachDefaultRole(User $user): void - { - $this->userRepo->attachDefaultRole($user); - } - } \ No newline at end of file From 58df3ad9566061186e62110e7c1e4a4140ed02c2 Mon Sep 17 00:00:00 2001 From: benrubson <6764151+benrubson@users.noreply.github.com> Date: Sun, 3 May 2020 16:20:02 +0200 Subject: [PATCH 056/197] Log failed accesses option --- .env.example.complete | 8 ++++++- app/Http/Controllers/Auth/LoginController.php | 21 ++++++++++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/.env.example.complete b/.env.example.complete index 04cd73b90..5b62b1a2a 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -266,4 +266,10 @@ API_DEFAULT_ITEM_COUNT=100 API_MAX_ITEM_COUNT=500 # The number of API requests that can be made per minute by a single user. -API_REQUESTS_PER_MIN=180 \ No newline at end of file +API_REQUESTS_PER_MIN=180 + +# Failed access +# message to log into webserver logs in case of failed access, for further processing by tools like Fail2Ban +# Apache users should use : user "%u" authentication failure for "BookStack" +# Nginx users should use : user "%u" was not found in "BookStack" +FAILED_ACCESS_MESSAGE='' diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 75ade74e7..c000af49e 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -169,15 +169,20 @@ class LoginController extends Controller } /** - * Log failed accesses, matching the default fail2ban nginx/apache auth rules. - */ - protected function logFailedAccess(Request $request) + * Log failed accesses, for further processing by tools like Fail2Ban + * + * @param \Illuminate\Http\Request $request + * @return void + */ + protected function logFailedAccess($request) { - if (isset($_SERVER['SERVER_SOFTWARE']) && preg_match('/nginx/i', $_SERVER['SERVER_SOFTWARE'])) { - error_log('user "' . $request->get($this->username()) . '" was not found in "BookStack"', 4); - } else { - error_log('user "' . $request->get($this->username()) . '" authentication failure for "BookStack"', 4); - } + $log_msg = env('FAILED_ACCESS_MESSAGE', ''); + + if (!is_string($request->get($this->username())) || !is_string($log_msg) || strlen($log_msg)<1) + return; + + $log_msg = str_replace("%u", $request->get($this->username()), $log_msg); + error_log($log_msg, 4); } } From 9666c8c0f773ef0fac899e394485d255a70a3802 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 May 2020 22:21:45 +0100 Subject: [PATCH 057/197] Updated shelf-list view to enforce view permissions for child books - Aligned shelf-homepage behaviour to match - Updated testing to cover. For #2111 --- app/Entities/Repos/BookshelfRepo.php | 6 ++++-- app/Http/Controllers/HomeController.php | 4 ---- resources/views/shelves/list-item.blade.php | 2 +- tests/Entity/BookShelfTest.php | 19 +++++++++++++++++++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/app/Entities/Repos/BookshelfRepo.php b/app/Entities/Repos/BookshelfRepo.php index 876f56e10..ba687c6f6 100644 --- a/app/Entities/Repos/BookshelfRepo.php +++ b/app/Entities/Repos/BookshelfRepo.php @@ -28,8 +28,10 @@ class BookshelfRepo */ public function getAllPaginated(int $count = 20, string $sort = 'name', string $order = 'asc'): LengthAwarePaginator { - return Bookshelf::visible()->with('visibleBooks') - ->orderBy($sort, $order)->paginate($count); + return Bookshelf::visible() + ->with('visibleBooks') + ->orderBy($sort, $order) + ->paginate($count); } /** diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 260952fd1..60d2664d0 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -69,11 +69,7 @@ class HomeController extends Controller } if ($homepageOption === 'bookshelves') { - $shelfRepo = app(BookshelfRepo::class); $shelves = app(BookshelfRepo::class)->getAllPaginated(18, $commonData['sort'], $commonData['order']); - foreach ($shelves as $shelf) { - $shelf->books = $shelf->visibleBooks; - } $data = array_merge($commonData, ['shelves' => $shelves]); return view('common.home-shelves', $data); } diff --git a/resources/views/shelves/list-item.blade.php b/resources/views/shelves/list-item.blade.php index c9c9670c5..6e5ed29a5 100644 --- a/resources/views/shelves/list-item.blade.php +++ b/resources/views/shelves/list-item.blade.php @@ -10,7 +10,7 @@
    - @foreach($shelf->books as $book) + @foreach($shelf->visibleBooks as $book)
    @icon('book') diff --git a/tests/Entity/BookShelfTest.php b/tests/Entity/BookShelfTest.php index abee4d34a..cb3acfb1e 100644 --- a/tests/Entity/BookShelfTest.php +++ b/tests/Entity/BookShelfTest.php @@ -56,6 +56,25 @@ class BookShelfTest extends TestCase $resp->assertElementContains('a', 'New Shelf'); } + public function test_book_not_visible_in_shelf_list_view_if_user_cant_view_shelf() + { + config()->set([ + 'app.views.bookshelves' => 'list', + ]); + $shelf = Bookshelf::query()->first(); + $book = $shelf->books()->first(); + + $resp = $this->asEditor()->get('/shelves'); + $resp->assertSee($book->name); + $resp->assertSee($book->getUrl()); + + $this->setEntityRestrictions($book, []); + + $resp = $this->asEditor()->get('/shelves'); + $resp->assertDontSee($book->name); + $resp->assertDontSee($book->getUrl()); + } + public function test_shelves_create() { $booksToInclude = Book::take(2)->get(); From 24bad5034af0142b43c97c4dad0353bb490b54c8 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 22 May 2020 22:34:18 +0100 Subject: [PATCH 058/197] Updated API auth to allow public user if given permission --- app/Http/Middleware/ApiAuthenticate.php | 4 ++-- tests/Api/ApiDocsTest.php | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/Http/Middleware/ApiAuthenticate.php b/app/Http/Middleware/ApiAuthenticate.php index 15962b3b0..728057bed 100644 --- a/app/Http/Middleware/ApiAuthenticate.php +++ b/app/Http/Middleware/ApiAuthenticate.php @@ -35,9 +35,9 @@ class ApiAuthenticate { // Return if the user is already found to be signed in via session-based auth. // This is to make it easy to browser the API via browser after just logging into the system. - if (signedInUser()) { + if (signedInUser() || session()->isStarted()) { $this->ensureEmailConfirmedIfRequested(); - if (!auth()->user()->can('access-api')) { + if (!user()->can('access-api')) { throw new ApiAuthException(trans('errors.api_user_no_api_permission'), 403); } return; diff --git a/tests/Api/ApiDocsTest.php b/tests/Api/ApiDocsTest.php index 3cbcadfa3..1687c64a1 100644 --- a/tests/Api/ApiDocsTest.php +++ b/tests/Api/ApiDocsTest.php @@ -1,5 +1,6 @@ setSettings(['app-public' => true]); + $guest = User::getDefault(); + + $this->startSession(); + $resp = $this->get('/api/docs'); + $resp->assertStatus(403); + + $this->giveUserPermissions($guest, ['access-api']); + + $resp = $this->get('/api/docs'); + $resp->assertStatus(200); + } } \ No newline at end of file From 8a6cf0cdecf8596c7cd4809188712f575c9e8202 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 May 2020 00:28:41 +0100 Subject: [PATCH 059/197] Added chapters to the API --- app/Actions/Tag.php | 1 + app/Actions/TagRepo.php | 5 +- app/Auth/User.php | 2 +- app/Entities/Book.php | 2 +- app/Entities/Bookshelf.php | 2 +- app/Entities/Chapter.php | 1 + app/Entities/Entity.php | 4 +- app/Entities/Page.php | 2 + app/Entities/Repos/PageRepo.php | 2 +- ...piController.php => BookApiController.php} | 4 +- ...roller.php => BookExportApiController.php} | 3 +- .../Controllers/Api/ChapterApiController.php | 104 ++++++++++ .../Api/ChapterExportApiController.php | 54 +++++ dev/api/requests/chapters-create.json | 9 + dev/api/requests/chapters-update.json | 9 + dev/api/responses/books-read.json | 7 +- dev/api/responses/chapters-create.json | 38 ++++ dev/api/responses/chapters-list.json | 29 +++ dev/api/responses/chapters-read.json | 59 ++++++ dev/api/responses/chapters-update.json | 38 ++++ dev/api/responses/shelves-read.json | 7 +- routes/api.php | 28 ++- tests/Api/ChaptersApiTest.php | 186 ++++++++++++++++++ tests/Api/TestsApi.php | 10 + 24 files changed, 575 insertions(+), 31 deletions(-) rename app/Http/Controllers/Api/{BooksApiController.php => BookApiController.php} (96%) rename app/Http/Controllers/Api/{BooksExportApiController.php => BookExportApiController.php} (96%) create mode 100644 app/Http/Controllers/Api/ChapterApiController.php create mode 100644 app/Http/Controllers/Api/ChapterExportApiController.php create mode 100644 dev/api/requests/chapters-create.json create mode 100644 dev/api/requests/chapters-update.json create mode 100644 dev/api/responses/chapters-create.json create mode 100644 dev/api/responses/chapters-list.json create mode 100644 dev/api/responses/chapters-read.json create mode 100644 dev/api/responses/chapters-update.json create mode 100644 tests/Api/ChaptersApiTest.php diff --git a/app/Actions/Tag.php b/app/Actions/Tag.php index 38d0458e4..80a911508 100644 --- a/app/Actions/Tag.php +++ b/app/Actions/Tag.php @@ -9,6 +9,7 @@ use BookStack\Model; class Tag extends Model { protected $fillable = ['name', 'value', 'order']; + protected $hidden = ['id', 'entity_id', 'entity_type']; /** * Get the entity that this tag belongs to diff --git a/app/Actions/TagRepo.php b/app/Actions/TagRepo.php index 0cbfa4163..b8b1eb464 100644 --- a/app/Actions/TagRepo.php +++ b/app/Actions/TagRepo.php @@ -106,14 +106,13 @@ class TagRepo /** * Save an array of tags to an entity - * @param \BookStack\Entities\Entity $entity - * @param array $tags * @return array|\Illuminate\Database\Eloquent\Collection */ - public function saveTagsToEntity(Entity $entity, $tags = []) + public function saveTagsToEntity(Entity $entity, array $tags = []) { $entity->tags()->delete(); $newTags = []; + foreach ($tags as $tag) { if (trim($tag['name']) === '') { continue; diff --git a/app/Auth/User.php b/app/Auth/User.php index a581d9993..40718beb6 100644 --- a/app/Auth/User.php +++ b/app/Auth/User.php @@ -49,7 +49,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon */ protected $hidden = [ 'password', 'remember_token', 'system_name', 'email_confirmed', 'external_auth_id', 'email', - 'created_at', 'updated_at', + 'created_at', 'updated_at', 'image_id', ]; /** diff --git a/app/Entities/Book.php b/app/Entities/Book.php index 38b7d4a8c..af8344b88 100644 --- a/app/Entities/Book.php +++ b/app/Entities/Book.php @@ -19,7 +19,7 @@ class Book extends Entity implements HasCoverImage public $searchFactor = 2; protected $fillable = ['name', 'description']; - protected $hidden = ['restricted', 'pivot']; + protected $hidden = ['restricted', 'pivot', 'image_id']; /** * Get the url for this book. diff --git a/app/Entities/Bookshelf.php b/app/Entities/Bookshelf.php index c7ba840e0..474ba51cd 100644 --- a/app/Entities/Bookshelf.php +++ b/app/Entities/Bookshelf.php @@ -12,7 +12,7 @@ class Bookshelf extends Entity implements HasCoverImage protected $fillable = ['name', 'description', 'image_id']; - protected $hidden = ['restricted']; + protected $hidden = ['restricted', 'image_id']; /** * Get the books in this shelf. diff --git a/app/Entities/Chapter.php b/app/Entities/Chapter.php index 848bc6448..3290afcfa 100644 --- a/app/Entities/Chapter.php +++ b/app/Entities/Chapter.php @@ -12,6 +12,7 @@ class Chapter extends BookChild public $searchFactor = 1.3; protected $fillable = ['name', 'description', 'priority', 'book_id']; + protected $hidden = ['restricted', 'pivot']; /** * Get the pages that this chapter contains. diff --git a/app/Entities/Entity.php b/app/Entities/Entity.php index 5013c39cf..6a5894cac 100644 --- a/app/Entities/Entity.php +++ b/app/Entities/Entity.php @@ -288,7 +288,7 @@ class Entity extends Ownable public function rebuildPermissions() { /** @noinspection PhpUnhandledExceptionInspection */ - Permissions::buildJointPermissionsForEntity($this); + Permissions::buildJointPermissionsForEntity(clone $this); } /** @@ -297,7 +297,7 @@ class Entity extends Ownable public function indexForSearch() { $searchService = app()->make(SearchService::class); - $searchService->indexEntity($this); + $searchService->indexEntity(clone $this); } /** diff --git a/app/Entities/Page.php b/app/Entities/Page.php index 76dc628fb..d10786dda 100644 --- a/app/Entities/Page.php +++ b/app/Entities/Page.php @@ -27,6 +27,8 @@ class Page extends BookChild public $textField = 'text'; + protected $hidden = ['html', 'markdown', 'text', 'restricted', 'pivot']; + /** * Get the entities that are visible to the current user. */ diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index e49eeb1ef..d92085a61 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -211,7 +211,7 @@ class PageRepo */ protected function savePageRevision(Page $page, string $summary = null) { - $revision = new PageRevision($page->toArray()); + $revision = new PageRevision($page->getAttributes()); if (setting('app-editor') !== 'markdown') { $revision->markdown = ''; diff --git a/app/Http/Controllers/Api/BooksApiController.php b/app/Http/Controllers/Api/BookApiController.php similarity index 96% rename from app/Http/Controllers/Api/BooksApiController.php rename to app/Http/Controllers/Api/BookApiController.php index ac4ea171c..8333eba3a 100644 --- a/app/Http/Controllers/Api/BooksApiController.php +++ b/app/Http/Controllers/Api/BookApiController.php @@ -8,7 +8,7 @@ use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Http\Request; use Illuminate\Validation\ValidationException; -class BooksApiController extends ApiController +class BookApiController extends ApiController { protected $bookRepo; @@ -17,10 +17,12 @@ class BooksApiController extends ApiController 'create' => [ 'name' => 'required|string|max:255', 'description' => 'string|max:1000', + 'tags' => 'array', ], 'update' => [ 'name' => 'string|min:1|max:255', 'description' => 'string|max:1000', + 'tags' => 'array', ], ]; diff --git a/app/Http/Controllers/Api/BooksExportApiController.php b/app/Http/Controllers/Api/BookExportApiController.php similarity index 96% rename from app/Http/Controllers/Api/BooksExportApiController.php rename to app/Http/Controllers/Api/BookExportApiController.php index 605f8f408..31fe5250f 100644 --- a/app/Http/Controllers/Api/BooksExportApiController.php +++ b/app/Http/Controllers/Api/BookExportApiController.php @@ -5,9 +5,8 @@ use BookStack\Entities\ExportService; use BookStack\Entities\Repos\BookRepo; use Throwable; -class BooksExportApiController extends ApiController +class BookExportApiController extends ApiController { - protected $bookRepo; protected $exportService; diff --git a/app/Http/Controllers/Api/ChapterApiController.php b/app/Http/Controllers/Api/ChapterApiController.php new file mode 100644 index 000000000..50aa8834e --- /dev/null +++ b/app/Http/Controllers/Api/ChapterApiController.php @@ -0,0 +1,104 @@ + [ + 'book_id' => 'required|integer', + 'name' => 'required|string|max:255', + 'description' => 'string|max:1000', + 'tags' => 'array', + ], + 'update' => [ + 'book_id' => 'integer', + 'name' => 'string|min:1|max:255', + 'description' => 'string|max:1000', + 'tags' => 'array', + ], + ]; + + /** + * ChapterController constructor. + */ + public function __construct(ChapterRepo $chapterRepo) + { + $this->chapterRepo = $chapterRepo; + } + + /** + * Get a listing of chapters visible to the user. + */ + public function list() + { + $chapters = Chapter::visible(); + return $this->apiListingResponse($chapters, [ + 'id', 'book_id', 'name', 'slug', 'description', 'priority', + 'created_at', 'updated_at', 'created_by', 'updated_by', + ]); + } + + /** + * Create a new chapter in the system. + */ + public function create(Request $request) + { + $this->validate($request, $this->rules['create']); + + $bookId = $request->get('book_id'); + $book = Book::visible()->findOrFail($bookId); + $this->checkOwnablePermission('chapter-create', $book); + + $chapter = $this->chapterRepo->create($request->all(), $book); + Activity::add($chapter, 'chapter_create', $book->id); + + return response()->json($chapter->load(['tags'])); + } + + /** + * View the details of a single chapter. + */ + public function read(string $id) + { + $chapter = Chapter::visible()->with(['tags', 'createdBy', 'updatedBy', 'pages' => function (HasMany $query) { + $query->visible()->get(['id', 'name', 'slug']); + }])->findOrFail($id); + return response()->json($chapter); + } + + /** + * Update the details of a single chapter. + */ + public function update(Request $request, string $id) + { + $chapter = Chapter::visible()->findOrFail($id); + $this->checkOwnablePermission('chapter-update', $chapter); + + $updatedChapter = $this->chapterRepo->update($chapter, $request->all()); + Activity::add($chapter, 'chapter_update', $chapter->book->id); + + return response()->json($updatedChapter->load(['tags'])); + } + + /** + * Delete a chapter from the system. + */ + public function delete(string $id) + { + $chapter = Chapter::visible()->findOrFail($id); + $this->checkOwnablePermission('chapter-delete', $chapter); + + $this->chapterRepo->destroy($chapter); + Activity::addMessage('chapter_delete', $chapter->name, $chapter->book->id); + + return response('', 204); + } +} diff --git a/app/Http/Controllers/Api/ChapterExportApiController.php b/app/Http/Controllers/Api/ChapterExportApiController.php new file mode 100644 index 000000000..f19f29e9d --- /dev/null +++ b/app/Http/Controllers/Api/ChapterExportApiController.php @@ -0,0 +1,54 @@ +chapterRepo = $chapterRepo; + $this->exportService = $exportService; + parent::__construct(); + } + + /** + * Export a chapter as a PDF file. + * @throws Throwable + */ + public function exportPdf(int $id) + { + $chapter = Chapter::visible()->findOrFail($id); + $pdfContent = $this->exportService->chapterToPdf($chapter); + return $this->downloadResponse($pdfContent, $chapter->slug . '.pdf'); + } + + /** + * Export a chapter as a contained HTML file. + * @throws Throwable + */ + public function exportHtml(int $id) + { + $chapter = Chapter::visible()->findOrFail($id); + $htmlContent = $this->exportService->chapterToContainedHtml($chapter); + return $this->downloadResponse($htmlContent, $chapter->slug . '.html'); + } + + /** + * Export a chapter as a plain text file. + */ + public function exportPlainText(int $id) + { + $chapter = Chapter::visible()->findOrFail($id); + $textContent = $this->exportService->chapterToPlainText($chapter); + return $this->downloadResponse($textContent, $chapter->slug . '.txt'); + } +} diff --git a/dev/api/requests/chapters-create.json b/dev/api/requests/chapters-create.json new file mode 100644 index 000000000..ca06fc298 --- /dev/null +++ b/dev/api/requests/chapters-create.json @@ -0,0 +1,9 @@ +{ + "book_id": 1, + "name": "My fantastic new chapter", + "description": "This is a great new chapter that I've created via the API", + "tags": [ + {"name": "Category", "value": "Top Content"}, + {"name": "Rating", "value": "Highest"} + ] +} \ No newline at end of file diff --git a/dev/api/requests/chapters-update.json b/dev/api/requests/chapters-update.json new file mode 100644 index 000000000..6bd3a3e5c --- /dev/null +++ b/dev/api/requests/chapters-update.json @@ -0,0 +1,9 @@ +{ + "book_id": 1, + "name": "My fantastic updated chapter", + "description": "This is an updated chapter that I've altered via the API", + "tags": [ + {"name": "Category", "value": "Kinda Good Content"}, + {"name": "Rating", "value": "Medium"} + ] +} \ No newline at end of file diff --git a/dev/api/responses/books-read.json b/dev/api/responses/books-read.json index 11408e9ab..2e43f5f87 100644 --- a/dev/api/responses/books-read.json +++ b/dev/api/responses/books-read.json @@ -7,15 +7,12 @@ "updated_at": "2020-01-12 14:11:51", "created_by": { "id": 1, - "name": "Admin", - "image_id": 48 + "name": "Admin" }, "updated_by": { "id": 1, - "name": "Admin", - "image_id": 48 + "name": "Admin" }, - "image_id": 452, "tags": [ { "id": 13, diff --git a/dev/api/responses/chapters-create.json b/dev/api/responses/chapters-create.json new file mode 100644 index 000000000..7aac27687 --- /dev/null +++ b/dev/api/responses/chapters-create.json @@ -0,0 +1,38 @@ +{ + "book_id": 1, + "priority": 6, + "name": "My fantastic new chapter", + "description": "This is a great new chapter that I've created via the API", + "created_by": 1, + "updated_by": 1, + "slug": "my-fantastic-new-chapter", + "updated_at": "2020-05-22 22:59:55", + "created_at": "2020-05-22 22:59:55", + "id": 74, + "book": { + "id": 1, + "name": "BookStack User Guide", + "slug": "bookstack-user-guide", + "description": "This is a general guide on using BookStack on a day-to-day basis.", + "created_at": "2019-05-05 21:48:46", + "updated_at": "2019-12-11 20:57:31", + "created_by": 1, + "updated_by": 1 + }, + "tags": [ + { + "name": "Category", + "value": "Top Content", + "order": 0, + "created_at": "2020-05-22 22:59:55", + "updated_at": "2020-05-22 22:59:55" + }, + { + "name": "Rating", + "value": "Highest", + "order": 0, + "created_at": "2020-05-22 22:59:55", + "updated_at": "2020-05-22 22:59:55" + } + ] +} \ No newline at end of file diff --git a/dev/api/responses/chapters-list.json b/dev/api/responses/chapters-list.json new file mode 100644 index 000000000..0c1fc5fc2 --- /dev/null +++ b/dev/api/responses/chapters-list.json @@ -0,0 +1,29 @@ +{ + "data": [ + { + "id": 1, + "book_id": 1, + "name": "Content Creation", + "slug": "content-creation", + "description": "How to create documentation on whatever subject you need to write about.", + "priority": 3, + "created_at": "2019-05-05 21:49:56", + "updated_at": "2019-09-28 11:24:23", + "created_by": 1, + "updated_by": 1 + }, + { + "id": 2, + "book_id": 1, + "name": "Managing Content", + "slug": "managing-content", + "description": "How to keep things organised and orderly in the system for easier navigation and better user experience.", + "priority": 5, + "created_at": "2019-05-05 21:58:07", + "updated_at": "2019-10-17 15:05:34", + "created_by": 3, + "updated_by": 3 + } + ], + "total": 40 +} \ No newline at end of file diff --git a/dev/api/responses/chapters-read.json b/dev/api/responses/chapters-read.json new file mode 100644 index 000000000..2eddad895 --- /dev/null +++ b/dev/api/responses/chapters-read.json @@ -0,0 +1,59 @@ +{ + "id": 1, + "book_id": 1, + "slug": "content-creation", + "name": "Content Creation", + "description": "How to create documentation on whatever subject you need to write about.", + "priority": 3, + "created_at": "2019-05-05 21:49:56", + "updated_at": "2019-09-28 11:24:23", + "created_by": { + "id": 1, + "name": "Admin" + }, + "updated_by": { + "id": 1, + "name": "Admin" + }, + "tags": [ + { + "name": "Category", + "value": "Guide", + "order": 0, + "created_at": "2020-05-22 22:51:51", + "updated_at": "2020-05-22 22:51:51" + } + ], + "pages": [ + { + "id": 1, + "book_id": 1, + "chapter_id": 1, + "name": "How to create page content", + "slug": "how-to-create-page-content", + "priority": 0, + "created_at": "2019-05-05 21:49:58", + "updated_at": "2019-08-26 14:32:59", + "created_by": 1, + "updated_by": 1, + "draft": 0, + "revision_count": 2, + "template": 0 + }, + { + "id": 7, + "book_id": 1, + "chapter_id": 1, + "name": "Good book structure", + "slug": "good-book-structure", + "priority": 1, + "created_at": "2019-05-05 22:01:55", + "updated_at": "2019-06-06 12:03:04", + "created_by": 3, + "updated_by": 3, + "draft": 0, + "revision_count": 1, + "template": 0 + } + ] +} \ No newline at end of file diff --git a/dev/api/responses/chapters-update.json b/dev/api/responses/chapters-update.json new file mode 100644 index 000000000..a7edb15b0 --- /dev/null +++ b/dev/api/responses/chapters-update.json @@ -0,0 +1,38 @@ +{ + "id": 75, + "book_id": 1, + "slug": "my-fantastic-updated-chapter", + "name": "My fantastic updated chapter", + "description": "This is an updated chapter that I've altered via the API", + "priority": 7, + "created_at": "2020-05-22 23:03:35", + "updated_at": "2020-05-22 23:07:20", + "created_by": 1, + "updated_by": 1, + "book": { + "id": 1, + "name": "BookStack User Guide", + "slug": "bookstack-user-guide", + "description": "This is a general guide on using BookStack on a day-to-day basis.", + "created_at": "2019-05-05 21:48:46", + "updated_at": "2019-12-11 20:57:31", + "created_by": 1, + "updated_by": 1 + }, + "tags": [ + { + "name": "Category", + "value": "Kinda Good Content", + "order": 0, + "created_at": "2020-05-22 23:07:20", + "updated_at": "2020-05-22 23:07:20" + }, + { + "name": "Rating", + "value": "Medium", + "order": 0, + "created_at": "2020-05-22 23:07:20", + "updated_at": "2020-05-22 23:07:20" + } + ] +} \ No newline at end of file diff --git a/dev/api/responses/shelves-read.json b/dev/api/responses/shelves-read.json index 8a8e2348b..634fbb5a5 100644 --- a/dev/api/responses/shelves-read.json +++ b/dev/api/responses/shelves-read.json @@ -5,15 +5,12 @@ "description": "This is my shelf with some books", "created_by": { "id": 1, - "name": "Admin", - "image_id": 48 + "name": "Admin" }, "updated_by": { "id": 1, - "name": "Admin", - "image_id": 48 + "name": "Admin" }, - "image_id": 501, "created_at": "2020-04-10 13:24:09", "updated_at": "2020-04-10 13:31:04", "tags": [ diff --git a/routes/api.php b/routes/api.php index f9c27b62f..1b90d9b8f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -9,18 +9,28 @@ Route::get('docs', 'ApiDocsController@display'); Route::get('docs.json', 'ApiDocsController@json'); -Route::get('books', 'BooksApiController@list'); -Route::post('books', 'BooksApiController@create'); -Route::get('books/{id}', 'BooksApiController@read'); -Route::put('books/{id}', 'BooksApiController@update'); -Route::delete('books/{id}', 'BooksApiController@delete'); +Route::get('books', 'BookApiController@list'); +Route::post('books', 'BookApiController@create'); +Route::get('books/{id}', 'BookApiController@read'); +Route::put('books/{id}', 'BookApiController@update'); +Route::delete('books/{id}', 'BookApiController@delete'); -Route::get('books/{id}/export/html', 'BooksExportApiController@exportHtml'); -Route::get('books/{id}/export/pdf', 'BooksExportApiController@exportPdf'); -Route::get('books/{id}/export/plaintext', 'BooksExportApiController@exportPlainText'); +Route::get('books/{id}/export/html', 'BookExportApiController@exportHtml'); +Route::get('books/{id}/export/pdf', 'BookExportApiController@exportPdf'); +Route::get('books/{id}/export/plaintext', 'BookExportApiController@exportPlainText'); + +Route::get('chapters', 'ChapterApiController@list'); +Route::post('chapters', 'ChapterApiController@create'); +Route::get('chapters/{id}', 'ChapterApiController@read'); +Route::put('chapters/{id}', 'ChapterApiController@update'); +Route::delete('chapters/{id}', 'ChapterApiController@delete'); + +Route::get('chapters/{id}/export/html', 'ChapterExportApiController@exportHtml'); +Route::get('chapters/{id}/export/pdf', 'ChapterExportApiController@exportPdf'); +Route::get('chapters/{id}/export/plaintext', 'ChapterExportApiController@exportPlainText'); Route::get('shelves', 'BookshelfApiController@list'); Route::post('shelves', 'BookshelfApiController@create'); Route::get('shelves/{id}', 'BookshelfApiController@read'); Route::put('shelves/{id}', 'BookshelfApiController@update'); -Route::delete('shelves/{id}', 'BookshelfApiController@delete'); \ No newline at end of file +Route::delete('shelves/{id}', 'BookshelfApiController@delete'); diff --git a/tests/Api/ChaptersApiTest.php b/tests/Api/ChaptersApiTest.php new file mode 100644 index 000000000..15a44459e --- /dev/null +++ b/tests/Api/ChaptersApiTest.php @@ -0,0 +1,186 @@ +actingAsApiEditor(); + $firstChapter = Chapter::query()->orderBy('id', 'asc')->first(); + + $resp = $this->getJson($this->baseEndpoint . '?count=1&sort=+id'); + $resp->assertJson(['data' => [ + [ + 'id' => $firstChapter->id, + 'name' => $firstChapter->name, + 'slug' => $firstChapter->slug, + 'book_id' => $firstChapter->book->id, + 'priority' => $firstChapter->priority, + ] + ]]); + } + + public function test_create_endpoint() + { + $this->actingAsApiEditor(); + $book = Book::query()->first(); + $details = [ + 'name' => 'My API chapter', + 'description' => 'A chapter created via the API', + 'book_id' => $book->id, + 'tags' => [ + [ + 'name' => 'tagname', + 'value' => 'tagvalue', + ] + ] + ]; + + $resp = $this->postJson($this->baseEndpoint, $details); + $resp->assertStatus(200); + $newItem = Chapter::query()->orderByDesc('id')->where('name', '=', $details['name'])->first(); + $resp->assertJson(array_merge($details, ['id' => $newItem->id, 'slug' => $newItem->slug])); + $this->assertDatabaseHas('tags', [ + 'entity_id' => $newItem->id, + 'entity_type' => $newItem->getMorphClass(), + 'name' => 'tagname', + 'value' => 'tagvalue', + ]); + $resp->assertJsonMissing(['pages' => []]); + $this->assertActivityExists('chapter_create', $newItem); + } + + public function test_chapter_name_needed_to_create() + { + $this->actingAsApiEditor(); + $book = Book::query()->first(); + $details = [ + 'book_id' => $book->id, + 'description' => 'A chapter created via the API', + ]; + + $resp = $this->postJson($this->baseEndpoint, $details); + $resp->assertStatus(422); + $resp->assertJson($this->validationResponse([ + "name" => ["The name field is required."] + ])); + } + + public function test_chapter_book_id_needed_to_create() + { + $this->actingAsApiEditor(); + $details = [ + 'name' => 'My api chapter', + 'description' => 'A chapter created via the API', + ]; + + $resp = $this->postJson($this->baseEndpoint, $details); + $resp->assertStatus(422); + $resp->assertJson($this->validationResponse([ + "book_id" => ["The book id field is required."] + ])); + } + + public function test_read_endpoint() + { + $this->actingAsApiEditor(); + $chapter = Chapter::visible()->first(); + $page = $chapter->pages()->first(); + + $resp = $this->getJson($this->baseEndpoint . "/{$chapter->id}"); + $resp->assertStatus(200); + $resp->assertJson([ + 'id' => $chapter->id, + 'slug' => $chapter->slug, + 'created_by' => [ + 'name' => $chapter->createdBy->name, + ], + 'book_id' => $chapter->book_id, + 'updated_by' => [ + 'name' => $chapter->createdBy->name, + ], + 'pages' => [ + [ + 'id' => $page->id, + 'slug' => $page->slug, + 'name' => $page->name, + ] + ], + ]); + $resp->assertJsonCount($chapter->pages()->count(), 'pages'); + } + + public function test_update_endpoint() + { + $this->actingAsApiEditor(); + $chapter = Chapter::visible()->first(); + $details = [ + 'name' => 'My updated API chapter', + 'description' => 'A chapter created via the API', + 'tags' => [ + [ + 'name' => 'freshtag', + 'value' => 'freshtagval', + ] + ], + ]; + + $resp = $this->putJson($this->baseEndpoint . "/{$chapter->id}", $details); + $chapter->refresh(); + + $resp->assertStatus(200); + $resp->assertJson(array_merge($details, [ + 'id' => $chapter->id, 'slug' => $chapter->slug, 'book_id' => $chapter->book_id + ])); + $this->assertActivityExists('chapter_update', $chapter); + } + + public function test_delete_endpoint() + { + $this->actingAsApiEditor(); + $chapter = Chapter::visible()->first(); + $resp = $this->deleteJson($this->baseEndpoint . "/{$chapter->id}"); + + $resp->assertStatus(204); + $this->assertActivityExists('chapter_delete'); + } + + public function test_export_html_endpoint() + { + $this->actingAsApiEditor(); + $chapter = Chapter::visible()->first(); + + $resp = $this->get($this->baseEndpoint . "/{$chapter->id}/export/html"); + $resp->assertStatus(200); + $resp->assertSee($chapter->name); + $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.html"'); + } + + public function test_export_plain_text_endpoint() + { + $this->actingAsApiEditor(); + $chapter = Chapter::visible()->first(); + + $resp = $this->get($this->baseEndpoint . "/{$chapter->id}/export/plaintext"); + $resp->assertStatus(200); + $resp->assertSee($chapter->name); + $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.txt"'); + } + + public function test_export_pdf_endpoint() + { + $this->actingAsApiEditor(); + $chapter = Chapter::visible()->first(); + + $resp = $this->get($this->baseEndpoint . "/{$chapter->id}/export/pdf"); + $resp->assertStatus(200); + $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.pdf"'); + } +} \ No newline at end of file diff --git a/tests/Api/TestsApi.php b/tests/Api/TestsApi.php index 623fa6969..1ad4d14b6 100644 --- a/tests/Api/TestsApi.php +++ b/tests/Api/TestsApi.php @@ -23,6 +23,16 @@ trait TestsApi return ["error" => ["code" => $code, "message" => $message]]; } + /** + * Format the given (field_name => ["messages"]) array + * into a standard validation response format. + */ + protected function validationResponse(array $messages): array + { + $err = $this->errorResponse("The given data was invalid.", 422); + $err['error']['validation'] = $messages; + return $err; + } /** * Get an approved API auth header. */ From b61f950560d4300b337c843ca242261b1bba5686 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 May 2020 00:29:09 +0100 Subject: [PATCH 060/197] Incremented version number --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index d40040377..31c2e1d4b 100644 --- a/version +++ b/version @@ -1 +1 @@ -v0.28-dev +v0.30-dev From 00c0815808ffd98ee32aef8be56f1ba2dba85ea5 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 May 2020 00:46:13 +0100 Subject: [PATCH 061/197] Fixed issue where updated page content would not be indexed - Also updated html field of pages to not be fillable. (Since HTML should always go through app id parsing) Related to #2042 --- app/Entities/Page.php | 2 +- app/Entities/Repos/PageRepo.php | 5 ++--- tests/Entity/EntitySearchTest.php | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/app/Entities/Page.php b/app/Entities/Page.php index d10786dda..32ba2981d 100644 --- a/app/Entities/Page.php +++ b/app/Entities/Page.php @@ -21,7 +21,7 @@ use Permissions; */ class Page extends BookChild { - protected $fillable = ['name', 'html', 'priority', 'markdown']; + protected $fillable = ['name', 'priority', 'markdown']; protected $simpleAttributes = ['name', 'id', 'slug']; diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index d92085a61..fc585b4df 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -180,12 +180,11 @@ class PageRepo $page->template = ($input['template'] === 'true'); } + $pageContent = new PageContent($page); + $pageContent->setNewHTML($input['html']); $this->baseRepo->update($page, $input); // Update with new details - $page->fill($input); - $pageContent = new PageContent($page); - $pageContent->setNewHTML($input['html']); $page->revision_count++; if (setting('app-editor') !== 'markdown') { diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index 72eb808dc..956e46c37 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -277,4 +277,20 @@ class EntitySearchTest extends TestCase $search->assertSee($expectedShelf->name); } } + + public function test_search_works_on_updated_page_content() + { + $page = Page::query()->first(); + $this->asEditor(); + + $update = $this->put($page->getUrl(), [ + 'name' => $page->name, + 'html' => '

    dog pandabearmonster spaghetti

    ', + ]); + + $search = $this->asEditor()->get('/search?term=pandabearmonster'); + $search->assertStatus(200); + $search->assertSeeText($page->name); + $search->assertSee($page->getUrl()); + } } From bf4a3b73f87f7ce4f107ca45a292ab038703f20b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 May 2020 00:53:13 +0100 Subject: [PATCH 062/197] Updated listing endpoints to be clickable in api docs --- resources/views/api-docs/index.blade.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/views/api-docs/index.blade.php b/resources/views/api-docs/index.blade.php index e92b505cf..d9c3d6595 100644 --- a/resources/views/api-docs/index.blade.php +++ b/resources/views/api-docs/index.blade.php @@ -189,7 +189,11 @@
    {{ $endpoint['controller_method_kebab'] }}
    {{ $endpoint['method'] }} - {{ url($endpoint['uri']) }} + @if($endpoint['controller_method_kebab'] === 'list') + {{ url($endpoint['uri']) }} + @else + {{ url($endpoint['uri']) }} + @endif

    {{ $endpoint['description'] ?? '' }}

    @if($endpoint['body_params'] ?? false) From 8f1f73defa321f026d487b3e9344055746bc6f58 Mon Sep 17 00:00:00 2001 From: benrubson <6764151+benrubson@users.noreply.github.com> Date: Sat, 23 May 2020 12:06:37 +0200 Subject: [PATCH 063/197] Properly use env/config functions --- app/Config/logging.php | 5 +++++ app/Http/Controllers/Auth/LoginController.php | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/Config/logging.php b/app/Config/logging.php index 0b55dc24d..406b9f2f9 100644 --- a/app/Config/logging.php +++ b/app/Config/logging.php @@ -79,4 +79,9 @@ return [ ], ], + // Failed Access Message + // Defines the message to log into webserver logs in case of failed access, + // for further processing by tools like Fail2Ban. + 'failed_access_message' => env('FAILED_ACCESS_MESSAGE', ''), + ]; diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index c000af49e..cf9e44e43 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -176,7 +176,7 @@ class LoginController extends Controller */ protected function logFailedAccess($request) { - $log_msg = env('FAILED_ACCESS_MESSAGE', ''); + $log_msg = config('logging.failed_access_message'); if (!is_string($request->get($this->username())) || !is_string($log_msg) || strlen($log_msg)<1) return; From 19bfc8ad379744e76b72c3c737018e8ce5fe4815 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 May 2020 11:26:48 +0100 Subject: [PATCH 064/197] Prevented entity "Not Found" events from being logged - Added testing to cover, which was more hassle than thought since Laravel did not have built in log test helpers, so: - Added Log testing helper. Related to #2110 --- app/Config/logging.php | 7 +++++++ app/Exceptions/Handler.php | 2 +- phpcs.xml | 1 + tests/ErrorTest.php | 20 ++++++++++++++++++++ tests/SharedTestHelpers.php | 31 ++++++++++++++++++++++++++----- 5 files changed, 55 insertions(+), 6 deletions(-) diff --git a/app/Config/logging.php b/app/Config/logging.php index 0b55dc24d..375e84083 100644 --- a/app/Config/logging.php +++ b/app/Config/logging.php @@ -77,6 +77,13 @@ return [ 'driver' => 'monolog', 'handler' => NullHandler::class, ], + + // Testing channel + // Uses a shared testing instance during tests + // so that logs can be checked against. + 'testing' => [ + 'driver' => 'testing', + ], ], ]; diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index a3bc1e8b9..57078522b 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -9,7 +9,6 @@ use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use Illuminate\Http\Response; use Illuminate\Validation\ValidationException; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -26,6 +25,7 @@ class Handler extends ExceptionHandler HttpException::class, ModelNotFoundException::class, ValidationException::class, + NotFoundException::class, ]; /** diff --git a/phpcs.xml b/phpcs.xml index 009791fc9..ccde28033 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -3,6 +3,7 @@ The coding standard for BookStack. app */migrations/* + */tests/* \ No newline at end of file diff --git a/tests/ErrorTest.php b/tests/ErrorTest.php index a5e4a4a5e..8f6867cde 100644 --- a/tests/ErrorTest.php +++ b/tests/ErrorTest.php @@ -1,5 +1,8 @@ assertDontSeeText('Log in'); $notFound->assertSeeText('tester'); } + + public function test_item_not_found_does_not_get_logged_to_file() + { + $this->actingAs($this->getViewer()); + $handler = $this->withTestLogger(); + $book = Book::query()->first(); + + // Ensure we're seeing errors + Log::error('cat'); + $this->assertTrue($handler->hasErrorThatContains('cat')); + + $this->get('/books/arandomnotfouindbook'); + $this->get($book->getUrl('/chapter/arandomnotfouindchapter')); + $this->get($book->getUrl('/chapter/arandomnotfouindpages')); + + $this->assertCount(1, $handler->getRecords()); + } } \ No newline at end of file diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index f7b7d5edf..c7659a02d 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -16,7 +16,10 @@ use BookStack\Entities\Repos\PageRepo; use BookStack\Settings\SettingService; use BookStack\Uploads\HttpFetcher; use Illuminate\Support\Env; +use Illuminate\Support\Facades\Log; use Mockery; +use Monolog\Handler\TestHandler; +use Monolog\Logger; use Throwable; trait SharedTestHelpers @@ -69,14 +72,14 @@ trait SharedTestHelpers } /** - * Get an instance of a user with 'viewer' permissions - * @param $attributes - * @return mixed + * Get an instance of a user with 'viewer' permissions. */ - protected function getViewer($attributes = []) + protected function getViewer(array $attributes = []): User { $user = Role::getRole('viewer')->users()->first(); - if (!empty($attributes)) $user->forceFill($attributes)->save(); + if (!empty($attributes)) { + $user->forceFill($attributes)->save(); + } return $user; } @@ -277,4 +280,22 @@ trait SharedTestHelpers $this->assertStringStartsWith('You do not have permission to access', $error); } + /** + * Set a test handler as the logging interface for the application. + * Allows capture of logs for checking against during tests. + */ + protected function withTestLogger(): TestHandler + { + $monolog = new Logger('testing'); + $testHandler = new TestHandler(); + $monolog->pushHandler($testHandler); + + Log::extend('testing', function() use ($monolog) { + return $monolog; + }); + Log::setDefaultDriver('testing'); + + return $testHandler; + } + } \ No newline at end of file From 31514bae06aecc595312f8c1636d03f13871c3d8 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 May 2020 11:50:44 +0100 Subject: [PATCH 065/197] Updated framework and other deps --- composer.json | 6 +- composer.lock | 920 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 676 insertions(+), 250 deletions(-) diff --git a/composer.json b/composer.json index 80e8b0a61..59fc909d6 100644 --- a/composer.json +++ b/composer.json @@ -13,14 +13,14 @@ "ext-mbstring": "*", "ext-tidy": "*", "ext-xml": "*", - "barryvdh/laravel-dompdf": "^0.8.5", - "barryvdh/laravel-snappy": "^0.4.5", + "barryvdh/laravel-dompdf": "^0.8.6", + "barryvdh/laravel-snappy": "^0.4.7", "doctrine/dbal": "^2.9", "facade/ignition": "^1.4", "fideloper/proxy": "^4.0", "gathercontent/htmldiff": "^0.2.1", "intervention/image": "^2.5", - "laravel/framework": "^6.12", + "laravel/framework": "^6.18", "laravel/socialite": "^4.3.2", "league/commonmark": "^1.4", "league/flysystem-aws-s3-v3": "^1.0", diff --git a/composer.lock b/composer.lock index 3ddd28e5a..a8c3b1e50 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bbe47cff4f167fd6ce7047dff4602a78", + "content-hash": "34390536dd685e0bc49b179babaa06ec", "packages": [ { "name": "aws/aws-sdk-php", - "version": "3.134.3", + "version": "3.138.7", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "3de2711a47e7c3f5e93a5c83f019188fd23f852f" + "reference": "6b9f3fcea4dfa6092c628c790ca6d369a75453b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3de2711a47e7c3f5e93a5c83f019188fd23f852f", - "reference": "3de2711a47e7c3f5e93a5c83f019188fd23f852f", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6b9f3fcea4dfa6092c628c790ca6d369a75453b7", + "reference": "6b9f3fcea4dfa6092c628c790ca6d369a75453b7", "shasum": "" }, "require": { @@ -88,7 +88,7 @@ "s3", "sdk" ], - "time": "2020-04-03T18:11:51+00:00" + "time": "2020-05-22T18:11:09+00:00" }, { "name": "barryvdh/laravel-dompdf", @@ -342,16 +342,16 @@ }, { "name": "doctrine/dbal", - "version": "v2.10.1", + "version": "2.10.2", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8" + "reference": "aab745e7b6b2de3b47019da81e7225e14dcfdac8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8", - "reference": "c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/aab745e7b6b2de3b47019da81e7225e14dcfdac8", + "reference": "aab745e7b6b2de3b47019da81e7225e14dcfdac8", "shasum": "" }, "require": { @@ -363,9 +363,11 @@ "require-dev": { "doctrine/coding-standard": "^6.0", "jetbrains/phpstorm-stubs": "^2019.1", - "phpstan/phpstan": "^0.11.3", + "nikic/php-parser": "^4.4", + "phpstan/phpstan": "^0.12", "phpunit/phpunit": "^8.4.1", - "symfony/console": "^2.0.5|^3.0|^4.0|^5.0" + "symfony/console": "^2.0.5|^3.0|^4.0|^5.0", + "vimeo/psalm": "^3.11" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -430,7 +432,21 @@ "sqlserver", "sqlsrv" ], - "time": "2020-01-04T12:56:21+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", + "type": "tidelift" + } + ], + "time": "2020-04-20T17:19:26+00:00" }, { "name": "doctrine/event-manager", @@ -510,33 +526,37 @@ }, { "name": "doctrine/inflector", - "version": "1.3.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" + "reference": "18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", - "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7", + "reference": "18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.2" }, "require-dev": { - "phpunit/phpunit": "^6.2" + "doctrine/coding-standard": "^7.0", + "phpstan/phpstan": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-strict-rules": "^0.11", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" } }, "notification-url": "https://packagist.org/downloads/", @@ -565,15 +585,35 @@ "email": "schmittjoh@gmail.com" } ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", - "homepage": "http://www.doctrine-project.org", + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", "keywords": [ "inflection", - "pluralize", - "singularize", - "string" + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" ], - "time": "2019-10-30T19:59:35+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2020-05-11T11:25:59+00:00" }, { "name": "doctrine/lexer", @@ -1040,16 +1080,16 @@ }, { "name": "filp/whoops", - "version": "2.7.1", + "version": "2.7.2", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "fff6f1e4f36be0e0d0b84d66b413d9dcb0c49130" + "reference": "17d0d3f266c8f925ebd035cd36f83cf802b47d4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/fff6f1e4f36be0e0d0b84d66b413d9dcb0c49130", - "reference": "fff6f1e4f36be0e0d0b84d66b413d9dcb0c49130", + "url": "https://api.github.com/repos/filp/whoops/zipball/17d0d3f266c8f925ebd035cd36f83cf802b47d4a", + "reference": "17d0d3f266c8f925ebd035cd36f83cf802b47d4a", "shasum": "" }, "require": { @@ -1097,7 +1137,7 @@ "throwable", "whoops" ], - "time": "2020-01-15T10:00:00+00:00" + "time": "2020-05-05T12:28:07+00:00" }, { "name": "gathercontent/htmldiff", @@ -1150,23 +1190,24 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.5.2", + "version": "6.5.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "43ece0e75098b7ecd8d13918293029e555a50f82" + "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82", - "reference": "43ece0e75098b7ecd8d13918293029e555a50f82", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/aab4ebd862aa7d04f01a4b51849d657db56d882e", + "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/promises": "^1.0", "guzzlehttp/psr7": "^1.6.1", - "php": ">=5.5" + "php": ">=5.5", + "symfony/polyfill-intl-idn": "^1.11" }, "require-dev": { "ext-curl": "*", @@ -1174,7 +1215,6 @@ "psr/log": "^1.1" }, "suggest": { - "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, "type": "library", @@ -1213,7 +1253,7 @@ "rest", "web service" ], - "time": "2019-12-23T11:57:10+00:00" + "time": "2020-04-18T10:38:46+00:00" }, { "name": "guzzlehttp/promises", @@ -1565,20 +1605,20 @@ }, { "name": "laravel/framework", - "version": "v6.18.3", + "version": "v6.18.15", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "4e48acfaba87f08320a2764d36c3b6a4a4112ccf" + "reference": "a1fa3ddc0bb5285cafa6844b443633f7627d75dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/4e48acfaba87f08320a2764d36c3b6a4a4112ccf", - "reference": "4e48acfaba87f08320a2764d36c3b6a4a4112ccf", + "url": "https://api.github.com/repos/laravel/framework/zipball/a1fa3ddc0bb5285cafa6844b443633f7627d75dc", + "reference": "a1fa3ddc0bb5285cafa6844b443633f7627d75dc", "shasum": "" }, "require": { - "doctrine/inflector": "^1.1", + "doctrine/inflector": "^1.4|^2.0", "dragonmantank/cron-expression": "^2.0", "egulias/email-validator": "^2.1.10", "ext-json": "*", @@ -1599,6 +1639,7 @@ "symfony/finder": "^4.3.4", "symfony/http-foundation": "^4.3.4", "symfony/http-kernel": "^4.3.4", + "symfony/polyfill-php73": "^1.17", "symfony/process": "^4.3.4", "symfony/routing": "^4.3.4", "symfony/var-dumper": "^4.3.4", @@ -1707,7 +1748,7 @@ "framework", "laravel" ], - "time": "2020-03-24T16:37:50+00:00" + "time": "2020-05-19T17:03:02+00:00" }, { "name": "laravel/socialite", @@ -1775,16 +1816,16 @@ }, { "name": "league/commonmark", - "version": "1.4.2", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "9e780d972185e4f737a03bade0fd34a9e67bbf31" + "reference": "412639f7cfbc0b31ad2455b2fe965095f66ae505" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/9e780d972185e4f737a03bade0fd34a9e67bbf31", - "reference": "9e780d972185e4f737a03bade0fd34a9e67bbf31", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/412639f7cfbc0b31ad2455b2fe965095f66ae505", + "reference": "412639f7cfbc0b31ad2455b2fe965095f66ae505", "shasum": "" }, "require": { @@ -1871,20 +1912,20 @@ "type": "tidelift" } ], - "time": "2020-04-24T13:39:56+00:00" + "time": "2020-05-04T22:15:21+00:00" }, { "name": "league/flysystem", - "version": "1.0.66", + "version": "1.0.69", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "021569195e15f8209b1c4bebb78bd66aa4f08c21" + "reference": "7106f78428a344bc4f643c233a94e48795f10967" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/021569195e15f8209b1c4bebb78bd66aa4f08c21", - "reference": "021569195e15f8209b1c4bebb78bd66aa4f08c21", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/7106f78428a344bc4f643c233a94e48795f10967", + "reference": "7106f78428a344bc4f643c233a94e48795f10967", "shasum": "" }, "require": { @@ -1955,7 +1996,13 @@ "sftp", "storage" ], - "time": "2020-03-17T18:58:12+00:00" + "funding": [ + { + "url": "https://offset.earth/frankdejonge", + "type": "other" + } + ], + "time": "2020-05-18T15:13:39+00:00" }, { "name": "league/flysystem-aws-s3-v3", @@ -2069,20 +2116,20 @@ }, { "name": "monolog/monolog", - "version": "2.0.2", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "c861fcba2ca29404dc9e617eedd9eff4616986b8" + "reference": "38914429aac460e8e4616c8cb486ecb40ec90bb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c861fcba2ca29404dc9e617eedd9eff4616986b8", - "reference": "c861fcba2ca29404dc9e617eedd9eff4616986b8", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/38914429aac460e8e4616c8cb486ecb40ec90bb1", + "reference": "38914429aac460e8e4616c8cb486ecb40ec90bb1", "shasum": "" }, "require": { - "php": "^7.2", + "php": ">=7.2", "psr/log": "^1.0.1" }, "provide": { @@ -2093,11 +2140,11 @@ "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^6.0", "graylog2/gelf-php": "^1.4.2", - "jakub-onderka/php-parallel-lint": "^0.9", "php-amqplib/php-amqplib": "~2.4", "php-console/php-console": "^3.1.3", + "php-parallel-lint/php-parallel-lint": "^1.0", "phpspec/prophecy": "^1.6.1", - "phpunit/phpunit": "^8.3", + "phpunit/phpunit": "^8.5", "predis/predis": "^1.1", "rollbar/rollbar": "^1.3", "ruflin/elastica": ">=0.90 <3.0", @@ -2146,7 +2193,17 @@ "logging", "psr-3" ], - "time": "2019-12-20T14:22:59+00:00" + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2020-05-22T08:12:19+00:00" }, { "name": "mtdowling/jmespath.php", @@ -2207,21 +2264,22 @@ }, { "name": "nesbot/carbon", - "version": "2.32.2", + "version": "2.34.2", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "f10e22cf546704fab1db4ad4b9dedbc5c797a0dc" + "reference": "3e87404329b8072295ea11d548b47a1eefe5a162" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f10e22cf546704fab1db4ad4b9dedbc5c797a0dc", - "reference": "f10e22cf546704fab1db4ad4b9dedbc5c797a0dc", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/3e87404329b8072295ea11d548b47a1eefe5a162", + "reference": "3e87404329b8072295ea11d548b47a1eefe5a162", "shasum": "" }, "require": { "ext-json": "*", "php": "^7.1.8 || ^8.0", + "symfony/polyfill-mbstring": "^1.0", "symfony/translation": "^3.4 || ^4.0 || ^5.0" }, "require-dev": { @@ -2239,7 +2297,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "2.x-dev", + "dev-3.x": "3.x-dev" }, "laravel": { "providers": [ @@ -2274,7 +2333,17 @@ "datetime", "time" ], - "time": "2020-03-31T13:43:19+00:00" + "funding": [ + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2020-05-19T22:14:16+00:00" }, { "name": "nunomaduro/collision", @@ -2392,16 +2461,16 @@ }, { "name": "opis/closure", - "version": "3.5.1", + "version": "3.5.2", "source": { "type": "git", "url": "https://github.com/opis/closure.git", - "reference": "93ebc5712cdad8d5f489b500c59d122df2e53969" + "reference": "2e3299cea6f485ca64d19c540f46d7896c512ace" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opis/closure/zipball/93ebc5712cdad8d5f489b500c59d122df2e53969", - "reference": "93ebc5712cdad8d5f489b500c59d122df2e53969", + "url": "https://api.github.com/repos/opis/closure/zipball/2e3299cea6f485ca64d19c540f46d7896c512ace", + "reference": "2e3299cea6f485ca64d19c540f46d7896c512ace", "shasum": "" }, "require": { @@ -2449,7 +2518,7 @@ "serialization", "serialize" ], - "time": "2019-11-29T22:36:02+00:00" + "time": "2020-05-21T20:09:36+00:00" }, { "name": "paragonie/random_compat", @@ -2498,20 +2567,20 @@ }, { "name": "phenx/php-font-lib", - "version": "0.5.1", + "version": "0.5.2", "source": { "type": "git", "url": "https://github.com/PhenX/php-font-lib.git", - "reference": "760148820110a1ae0936e5cc35851e25a938bc97" + "reference": "ca6ad461f032145fff5971b5985e5af9e7fa88d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/760148820110a1ae0936e5cc35851e25a938bc97", - "reference": "760148820110a1ae0936e5cc35851e25a938bc97", + "url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/ca6ad461f032145fff5971b5985e5af9e7fa88d8", + "reference": "ca6ad461f032145fff5971b5985e5af9e7fa88d8", "shasum": "" }, "require-dev": { - "phpunit/phpunit": "^4.8" + "phpunit/phpunit": "^4.8.35 || ^5 || ^6 || ^7" }, "type": "library", "autoload": { @@ -2531,7 +2600,7 @@ ], "description": "A library to read, parse, export and make subsets of different types of font files.", "homepage": "https://github.com/PhenX/php-font-lib", - "time": "2017-09-13T16:14:37+00:00" + "time": "2020-03-08T15:31:32+00:00" }, { "name": "phenx/php-svg-lib", @@ -3001,16 +3070,16 @@ }, { "name": "robrichards/xmlseclibs", - "version": "3.0.4", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/robrichards/xmlseclibs.git", - "reference": "0a53d3c3aa87564910cae4ed01416441d3ae0db5" + "reference": "8d8e56ca7914440a8c60caff1a865e7dff1d9a5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/0a53d3c3aa87564910cae4ed01416441d3ae0db5", - "reference": "0a53d3c3aa87564910cae4ed01416441d3ae0db5", + "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/8d8e56ca7914440a8c60caff1a865e7dff1d9a5a", + "reference": "8d8e56ca7914440a8c60caff1a865e7dff1d9a5a", "shasum": "" }, "require": { @@ -3035,7 +3104,7 @@ "xml", "xmldsig" ], - "time": "2019-11-05T11:44:22+00:00" + "time": "2020-04-22T17:19:51+00:00" }, { "name": "sabberworm/php-css-parser", @@ -3284,21 +3353,22 @@ }, { "name": "socialiteproviders/microsoft-azure", - "version": "v3.0.0", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Microsoft-Azure.git", - "reference": "d7a703a782eb9f7eae0db803beaa3ddec19ef372" + "reference": "b22f4696cccecd6de902cf0bc923de7fc2e4608e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Microsoft-Azure/zipball/d7a703a782eb9f7eae0db803beaa3ddec19ef372", - "reference": "d7a703a782eb9f7eae0db803beaa3ddec19ef372", + "url": "https://api.github.com/repos/SocialiteProviders/Microsoft-Azure/zipball/b22f4696cccecd6de902cf0bc923de7fc2e4608e", + "reference": "b22f4696cccecd6de902cf0bc923de7fc2e4608e", "shasum": "" }, "require": { + "ext-json": "*", "php": "^5.6 || ^7.0", - "socialiteproviders/manager": "~3.0" + "socialiteproviders/manager": "~2.0 || ~3.0" }, "type": "library", "autoload": { @@ -3317,23 +3387,24 @@ } ], "description": "Microsoft Azure OAuth2 Provider for Laravel Socialite", - "time": "2017-01-25T09:48:29+00:00" + "time": "2020-04-30T23:01:40+00:00" }, { "name": "socialiteproviders/okta", - "version": "v1.0.0", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Okta.git", - "reference": "dcda13432c80060cd84d4cb5f2af422d280ab895" + "reference": "7c2512f0872316b139e3eea1c50c9351747a57ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Okta/zipball/dcda13432c80060cd84d4cb5f2af422d280ab895", - "reference": "dcda13432c80060cd84d4cb5f2af422d280ab895", + "url": "https://api.github.com/repos/SocialiteProviders/Okta/zipball/7c2512f0872316b139e3eea1c50c9351747a57ea", + "reference": "7c2512f0872316b139e3eea1c50c9351747a57ea", "shasum": "" }, "require": { + "ext-json": "*", "php": "^5.6 || ^7.0", "socialiteproviders/manager": "~2.0 || ~3.0" }, @@ -3354,7 +3425,7 @@ } ], "description": "Okta OAuth2 Provider for Laravel Socialite", - "time": "2017-11-21T05:31:47+00:00" + "time": "2019-09-06T15:27:03+00:00" }, { "name": "socialiteproviders/slack", @@ -3395,19 +3466,20 @@ }, { "name": "socialiteproviders/twitch", - "version": "v5.1", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Twitch.git", - "reference": "f9b1f90a94f539e1b29e84ee0f731f42d59f3213" + "reference": "9ee6fe196d7c28777139b3cde04cbd537cf7e652" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Twitch/zipball/f9b1f90a94f539e1b29e84ee0f731f42d59f3213", - "reference": "f9b1f90a94f539e1b29e84ee0f731f42d59f3213", + "url": "https://api.github.com/repos/SocialiteProviders/Twitch/zipball/9ee6fe196d7c28777139b3cde04cbd537cf7e652", + "reference": "9ee6fe196d7c28777139b3cde04cbd537cf7e652", "shasum": "" }, "require": { + "ext-json": "*", "php": "^5.6 || ^7.0", "socialiteproviders/manager": "~2.0 || ~3.0" }, @@ -3428,7 +3500,7 @@ } ], "description": "Twitch OAuth2 Provider for Laravel Socialite", - "time": "2019-07-01T10:35:46+00:00" + "time": "2020-05-06T22:51:30+00:00" }, { "name": "swiftmailer/swiftmailer", @@ -3494,7 +3566,7 @@ }, { "name": "symfony/console", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", @@ -3566,11 +3638,25 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-30T11:41:10+00:00" }, { "name": "symfony/css-selector", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -3619,11 +3705,25 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/debug", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", @@ -3675,11 +3775,25 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/error-handler", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", @@ -3731,11 +3845,25 @@ ], "description": "Symfony ErrorHandler Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-30T14:07:33+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -3801,6 +3929,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-27T16:54:36+00:00" }, { @@ -3863,7 +4005,7 @@ }, { "name": "symfony/finder", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -3908,20 +4050,34 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/http-foundation", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "62f92509c9abfd1f73e17b8cf1b72c0bdac6611b" + "reference": "ec5bd254c223786f5fa2bb49a1e705c1b8e7cee2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/62f92509c9abfd1f73e17b8cf1b72c0bdac6611b", - "reference": "62f92509c9abfd1f73e17b8cf1b72c0bdac6611b", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ec5bd254c223786f5fa2bb49a1e705c1b8e7cee2", + "reference": "ec5bd254c223786f5fa2bb49a1e705c1b8e7cee2", "shasum": "" }, "require": { @@ -3963,20 +4119,34 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2020-03-30T14:07:33+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-04-18T20:40:08+00:00" }, { "name": "symfony/http-kernel", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "f356a489e51856b99908005eb7f2c51a1dfc95dc" + "reference": "1799a6c01f0db5851f399151abdb5d6393fec277" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f356a489e51856b99908005eb7f2c51a1dfc95dc", - "reference": "f356a489e51856b99908005eb7f2c51a1dfc95dc", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/1799a6c01f0db5851f399151abdb5d6393fec277", + "reference": "1799a6c01f0db5851f399151abdb5d6393fec277", "shasum": "" }, "require": { @@ -4053,20 +4223,34 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2020-03-30T14:59:15+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-04-28T18:47:42+00:00" }, { "name": "symfony/mime", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "6dde9dc70155e91b850b1d009d1f841c54bc4aba" + "reference": "7a583ffb6c7dd5aabb5db920817a3cc39261c517" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/6dde9dc70155e91b850b1d009d1f841c54bc4aba", - "reference": "6dde9dc70155e91b850b1d009d1f841c54bc4aba", + "url": "https://api.github.com/repos/symfony/mime/zipball/7a583ffb6c7dd5aabb5db920817a3cc39261c517", + "reference": "7a583ffb6c7dd5aabb5db920817a3cc39261c517", "shasum": "" }, "require": { @@ -4115,20 +4299,34 @@ "mime", "mime-type" ], - "time": "2020-03-27T16:54:36+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-04-16T14:49:30+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", - "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9", + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9", "shasum": "" }, "require": { @@ -4140,7 +4338,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4173,20 +4371,34 @@ "polyfill", "portable" ], - "time": "2020-02-27T09:26:54+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-12T16:14:59+00:00" }, { "name": "symfony/polyfill-iconv", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8" + "reference": "c4de7601eefbf25f9d47190abe07f79fe0a27424" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/ad6d62792bfbcfc385dd34b424d4fcf9712a32c8", - "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/c4de7601eefbf25f9d47190abe07f79fe0a27424", + "reference": "c4de7601eefbf25f9d47190abe07f79fe0a27424", "shasum": "" }, "require": { @@ -4198,7 +4410,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4232,20 +4444,34 @@ "portable", "shim" ], - "time": "2020-03-09T19:04:49+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf" + "reference": "3bff59ea7047e925be6b7f2059d60af31bb46d6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", - "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/3bff59ea7047e925be6b7f2059d60af31bb46d6a", + "reference": "3bff59ea7047e925be6b7f2059d60af31bb46d6a", "shasum": "" }, "require": { @@ -4259,7 +4485,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4294,20 +4520,34 @@ "portable", "shim" ], - "time": "2020-03-09T19:04:49+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", - "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c", + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c", "shasum": "" }, "require": { @@ -4319,7 +4559,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4353,20 +4593,34 @@ "portable", "shim" ], - "time": "2020-03-09T19:04:49+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "37b0976c78b94856543260ce09b460a7bc852747" + "reference": "f048e612a3905f34931127360bdd2def19a5e582" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747", - "reference": "37b0976c78b94856543260ce09b460a7bc852747", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/f048e612a3905f34931127360bdd2def19a5e582", + "reference": "f048e612a3905f34931127360bdd2def19a5e582", "shasum": "" }, "require": { @@ -4375,7 +4629,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4408,20 +4662,34 @@ "portable", "shim" ], - "time": "2020-02-27T09:26:54+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7" + "reference": "a760d8964ff79ab9bf057613a5808284ec852ccc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", - "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a760d8964ff79ab9bf057613a5808284ec852ccc", + "reference": "a760d8964ff79ab9bf057613a5808284ec852ccc", "shasum": "" }, "require": { @@ -4430,7 +4698,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4466,20 +4734,34 @@ "portable", "shim" ], - "time": "2020-02-27T09:26:54+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/process", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "3e40e87a20eaf83a1db825e1fa5097ae89042db3" + "reference": "4b6a9a4013baa65d409153cbb5a895bf093dc7f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/3e40e87a20eaf83a1db825e1fa5097ae89042db3", - "reference": "3e40e87a20eaf83a1db825e1fa5097ae89042db3", + "url": "https://api.github.com/repos/symfony/process/zipball/4b6a9a4013baa65d409153cbb5a895bf093dc7f4", + "reference": "4b6a9a4013baa65d409153cbb5a895bf093dc7f4", "shasum": "" }, "require": { @@ -4515,20 +4797,34 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2020-03-27T16:54:36+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-04-15T15:56:18+00:00" }, { "name": "symfony/routing", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "0f562fa613e288d7dbae6c63abbc9b33ed75a8f8" + "reference": "67b4e1f99c050cbc310b8f3d0dbdc4b0212c052c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0f562fa613e288d7dbae6c63abbc9b33ed75a8f8", - "reference": "0f562fa613e288d7dbae6c63abbc9b33ed75a8f8", + "url": "https://api.github.com/repos/symfony/routing/zipball/67b4e1f99c050cbc310b8f3d0dbdc4b0212c052c", + "reference": "67b4e1f99c050cbc310b8f3d0dbdc4b0212c052c", "shasum": "" }, "require": { @@ -4591,7 +4887,21 @@ "uri", "url" ], - "time": "2020-03-30T11:41:10+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-04-21T19:59:53+00:00" }, { "name": "symfony/service-contracts", @@ -4653,16 +4963,16 @@ }, { "name": "symfony/translation", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "4e54d336f2eca5facad449d0b0118bb449375b76" + "reference": "8272bbd2b7e220ef812eba2a2b30068a5c64b191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/4e54d336f2eca5facad449d0b0118bb449375b76", - "reference": "4e54d336f2eca5facad449d0b0118bb449375b76", + "url": "https://api.github.com/repos/symfony/translation/zipball/8272bbd2b7e220ef812eba2a2b30068a5c64b191", + "reference": "8272bbd2b7e220ef812eba2a2b30068a5c64b191", "shasum": "" }, "require": { @@ -4725,7 +5035,21 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2020-03-27T16:54:36+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-04-12T16:45:36+00:00" }, { "name": "symfony/translation-contracts", @@ -4786,16 +5110,16 @@ }, { "name": "symfony/var-dumper", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "5a0c2d93006131a36cf6f767d10e2ca8333b0d4a" + "reference": "c587e04ce5d1aa62d534a038f574d9a709e814cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/5a0c2d93006131a36cf6f767d10e2ca8333b0d4a", - "reference": "5a0c2d93006131a36cf6f767d10e2ca8333b0d4a", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c587e04ce5d1aa62d534a038f574d9a709e814cf", + "reference": "c587e04ce5d1aa62d534a038f574d9a709e814cf", "shasum": "" }, "require": { @@ -4858,7 +5182,21 @@ "debug", "dump" ], - "time": "2020-03-27T16:54:36+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-04-12T16:14:02+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -4911,20 +5249,20 @@ }, { "name": "vlucas/phpdotenv", - "version": "v3.6.2", + "version": "v3.6.4", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "786a947e57086cf236cefdee80784634224b99fa" + "reference": "10d3f853fdf1f3a6b3c7ea0c4620d2f699713db5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/786a947e57086cf236cefdee80784634224b99fa", - "reference": "786a947e57086cf236cefdee80784634224b99fa", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/10d3f853fdf1f3a6b3c7ea0c4620d2f699713db5", + "reference": "10d3f853fdf1f3a6b3c7ea0c4620d2f699713db5", "shasum": "" }, "require": { - "php": "^5.4 || ^7.0", + "php": "^5.4 || ^7.0 || ^8.0", "phpoption/phpoption": "^1.5", "symfony/polyfill-ctype": "^1.9" }, @@ -4970,22 +5308,32 @@ "env", "environment" ], - "time": "2020-03-27T23:36:02+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2020-05-02T13:46:13+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.2.9", + "version": "v3.3.3", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "42d5da5379a7860093f8e4032167e4cb5ebec180" + "reference": "57f2219f6d9efe41ed1bc880d86701c52f261bf5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/42d5da5379a7860093f8e4032167e4cb5ebec180", - "reference": "42d5da5379a7860093f8e4032167e4cb5ebec180", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/57f2219f6d9efe41ed1bc880d86701c52f261bf5", + "reference": "57f2219f6d9efe41ed1bc880d86701c52f261bf5", "shasum": "" }, "require": { @@ -5040,20 +5388,26 @@ "profiler", "webprofiler" ], - "time": "2020-02-25T20:42:23+00:00" + "funding": [ + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2020-05-05T10:53:32+00:00" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v2.6.7", + "version": "v2.7.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "edd69c5e0508972c81f1f7173236de2459c45814" + "reference": "5f677edc14bdcfdcac36633e6eea71b2728a4dbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/edd69c5e0508972c81f1f7173236de2459c45814", - "reference": "edd69c5e0508972c81f1f7173236de2459c45814", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/5f677edc14bdcfdcac36633e6eea71b2728a4dbc", + "reference": "5f677edc14bdcfdcac36633e6eea71b2728a4dbc", "shasum": "" }, "require": { @@ -5069,7 +5423,7 @@ "illuminate/config": "^5.5|^6|^7", "illuminate/view": "^5.5|^6|^7", "mockery/mockery": "^1.3", - "orchestra/testbench": "^3|^4", + "orchestra/testbench": "^3|^4|^5", "phpro/grumphp": "^0.17.1", "squizlabs/php_codesniffer": "^3" }, @@ -5111,7 +5465,13 @@ "phpstorm", "sublime" ], - "time": "2020-02-25T20:41:32+00:00" + "funding": [ + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2020-04-22T09:57:26+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -5164,16 +5524,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.2.6", + "version": "1.2.7", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e" + "reference": "95c63ab2117a72f48f5a55da9740a3273d45b7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/47fe531de31fca4a1b997f87308e7d7804348f7e", - "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/95c63ab2117a72f48f5a55da9740a3273d45b7fd", + "reference": "95c63ab2117a72f48f5a55da9740a3273d45b7fd", "shasum": "" }, "require": { @@ -5216,20 +5576,30 @@ "ssl", "tls" ], - "time": "2020-01-13T10:02:55+00:00" + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2020-04-08T08:27:21+00:00" }, { "name": "composer/composer", - "version": "1.10.1", + "version": "1.10.6", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "b912a45da3e2b22f5cb5a23e441b697a295ba011" + "reference": "be81b9c4735362c26876bdbfd3b5bc7e7f711c88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/b912a45da3e2b22f5cb5a23e441b697a295ba011", - "reference": "b912a45da3e2b22f5cb5a23e441b697a295ba011", + "url": "https://api.github.com/repos/composer/composer/zipball/be81b9c4735362c26876bdbfd3b5bc7e7f711c88", + "reference": "be81b9c4735362c26876bdbfd3b5bc7e7f711c88", "shasum": "" }, "require": { @@ -5248,7 +5618,8 @@ "symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0" }, "conflict": { - "symfony/console": "2.8.38" + "symfony/console": "2.8.38", + "symfony/phpunit-bridge": "3.4.40" }, "require-dev": { "phpspec/prophecy": "^1.10", @@ -5296,7 +5667,17 @@ "dependency", "package" ], - "time": "2020-03-13T19:34:27+00:00" + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2020-05-06T08:28:10+00:00" }, { "name": "composer/semver", @@ -5746,16 +6127,16 @@ }, { "name": "maximebf/debugbar", - "version": "v1.16.1", + "version": "v1.16.3", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "58998b818c6567fac01e35b8a4b70c1a64530556" + "reference": "1a1605b8e9bacb34cc0c6278206d699772e1d372" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/58998b818c6567fac01e35b8a4b70c1a64530556", - "reference": "58998b818c6567fac01e35b8a4b70c1a64530556", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/1a1605b8e9bacb34cc0c6278206d699772e1d372", + "reference": "1a1605b8e9bacb34cc0c6278206d699772e1d372", "shasum": "" }, "require": { @@ -5803,7 +6184,7 @@ "debug", "debugbar" ], - "time": "2019-11-24T09:46:11+00:00" + "time": "2020-05-06T07:06:27+00:00" }, { "name": "mockery/mockery", @@ -6022,24 +6403,21 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" + "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b", + "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b", "shasum": "" }, "require": { "php": ">=7.1" }, - "require-dev": { - "phpunit/phpunit": "~6" - }, "type": "library", "extra": { "branch-alias": { @@ -6070,7 +6448,7 @@ "reflection", "static analysis" ], - "time": "2018-08-07T13:53:10+00:00" + "time": "2020-04-27T09:25:28+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -6537,16 +6915,16 @@ }, { "name": "phpunit/phpunit", - "version": "8.5.3", + "version": "8.5.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "67750516bc02f300e2742fed2f50177f8f37bedf" + "reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/67750516bc02f300e2742fed2f50177f8f37bedf", - "reference": "67750516bc02f300e2742fed2f50177f8f37bedf", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/63dda3b212a0025d380a745f91bdb4d8c985adb7", + "reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7", "shasum": "" }, "require": { @@ -6616,7 +6994,17 @@ "testing", "xunit" ], - "time": "2020-03-31T08:52:04+00:00" + "funding": [ + { + "url": "https://phpunit.de/donate.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-05-22T13:51:52+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -7278,20 +7666,20 @@ }, { "name": "seld/jsonlint", - "version": "1.7.2", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "e2e5d290e4d2a4f0eb449f510071392e00e10d19" + "reference": "ff2aa5420bfbc296cf6a0bc785fa5b35736de7c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/e2e5d290e4d2a4f0eb449f510071392e00e10d19", - "reference": "e2e5d290e4d2a4f0eb449f510071392e00e10d19", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/ff2aa5420bfbc296cf6a0bc785fa5b35736de7c1", + "reference": "ff2aa5420bfbc296cf6a0bc785fa5b35736de7c1", "shasum": "" }, "require": { - "php": "^5.3 || ^7.0" + "php": "^5.3 || ^7.0 || ^8.0" }, "require-dev": { "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" @@ -7323,7 +7711,17 @@ "parser", "validator" ], - "time": "2019-10-24T14:27:39+00:00" + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", + "type": "tidelift" + } + ], + "time": "2020-04-30T19:05:18+00:00" }, { "name": "seld/phar-utils", @@ -7371,16 +7769,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.5.4", + "version": "3.5.5", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "dceec07328401de6211037abbb18bda423677e26" + "reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dceec07328401de6211037abbb18bda423677e26", - "reference": "dceec07328401de6211037abbb18bda423677e26", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/73e2e7f57d958e7228fce50dc0c61f58f017f9f6", + "reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6", "shasum": "" }, "require": { @@ -7418,11 +7816,11 @@ "phpcs", "standards" ], - "time": "2020-01-30T22:20:29+00:00" + "time": "2020-04-17T01:09:41+00:00" }, { "name": "symfony/dom-crawler", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", @@ -7479,20 +7877,34 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-29T19:12:22+00:00" }, { "name": "symfony/filesystem", - "version": "v4.4.7", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "fe297193bf2e6866ed900ed2d5869362768df6a7" + "reference": "a3ebf3bfd8a98a147c010a568add5a8aa4edea0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/fe297193bf2e6866ed900ed2d5869362768df6a7", - "reference": "fe297193bf2e6866ed900ed2d5869362768df6a7", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/a3ebf3bfd8a98a147c010a568add5a8aa4edea0f", + "reference": "a3ebf3bfd8a98a147c010a568add5a8aa4edea0f", "shasum": "" }, "require": { @@ -7529,7 +7941,21 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2020-03-27T16:54:36+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-04-12T14:39:55+00:00" }, { "name": "theseer/fdomdocument", @@ -7613,16 +8039,16 @@ }, { "name": "webmozart/assert", - "version": "1.7.0", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "aed98a490f9a8f78468232db345ab9cf606cf598" + "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598", - "reference": "aed98a490f9a8f78468232db345ab9cf606cf598", + "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6", + "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6", "shasum": "" }, "require": { @@ -7630,7 +8056,7 @@ "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "vimeo/psalm": "<3.6.0" + "vimeo/psalm": "<3.9.1" }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^7.5.13" @@ -7657,7 +8083,7 @@ "check", "validate" ], - "time": "2020-02-14T12:15:55+00:00" + "time": "2020-04-18T12:12:48+00:00" }, { "name": "wnx/laravel-stats", From 3502abdd49c1ca09e3529c7410ed626913682a8d Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 May 2020 12:28:14 +0100 Subject: [PATCH 066/197] Fixed revision issues caused by page fillable changes --- app/Entities/Repos/PageRepo.php | 2 +- app/Http/Controllers/PageRevisionController.php | 7 +++++++ tests/Entity/PageRevisionTest.php | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index fc585b4df..e5f13463c 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -278,7 +278,7 @@ class PageRepo $revision = $page->revisions()->where('id', '=', $revisionId)->first(); $page->fill($revision->toArray()); $content = new PageContent($page); - $content->setNewHTML($page->html); + $content->setNewHTML($revision->html); $page->updated_by = user()->id; $page->refreshSlug(); $page->save(); diff --git a/app/Http/Controllers/PageRevisionController.php b/app/Http/Controllers/PageRevisionController.php index 3c65b50ac..797f5db8f 100644 --- a/app/Http/Controllers/PageRevisionController.php +++ b/app/Http/Controllers/PageRevisionController.php @@ -1,5 +1,6 @@ fill($revision->toArray()); + // TODO - Refactor PageContent so we don't need to juggle this + $page->html = $revision->html; + $page->html = (new PageContent($page))->render(); $this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()])); return view('pages.revision', [ @@ -73,6 +77,9 @@ class PageRevisionController extends Controller $diff = (new Htmldiff)->diff($prevContent, $revision->html); $page->fill($revision->toArray()); + // TODO - Refactor PageContent so we don't need to juggle this + $page->html = $revision->html; + $page->html = (new PageContent($page))->render(); $this->setPageTitle(trans('entities.pages_revision_named', ['pageName'=>$page->getShortName()])); return view('pages.revision', [ diff --git a/tests/Entity/PageRevisionTest.php b/tests/Entity/PageRevisionTest.php index f8baccc54..1e9dbd626 100644 --- a/tests/Entity/PageRevisionTest.php +++ b/tests/Entity/PageRevisionTest.php @@ -24,6 +24,21 @@ class PageRevisionTest extends TestCase $revisionView->assertSee('new content'); } + public function test_page_revision_preview_shows_content_of_revision() + { + $this->asEditor(); + + $pageRepo = app(PageRepo::class); + $page = Page::first(); + $pageRepo->update($page, ['name' => 'updated page', 'html' => '

    new revision content

    ', 'summary' => 'page revision testing']); + $pageRevision = $page->revisions->last(); + $pageRepo->update($page, ['name' => 'updated page', 'html' => '

    Updated content

    ', 'summary' => 'page revision testing 2']); + + $revisionView = $this->get($page->getUrl() . '/revisions/' . $pageRevision->id); + $revisionView->assertStatus(200); + $revisionView->assertSee('new revision content'); + } + public function test_page_revision_restore_updates_content() { $this->asEditor(); From 71e7dd5894b855b0a6ed58fd520af49a521681c8 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 May 2020 12:56:31 +0100 Subject: [PATCH 067/197] Removed failing URL test - Was found that the test was not testing the actual situation anyway. - A work-around in the request creation, within testing, just happened to result in the desired outcome. For reference: https://github.com/laravel/framework/pull/32345 --- tests/Unit/UrlTest.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/Unit/UrlTest.php b/tests/Unit/UrlTest.php index feff47977..b9f485da1 100644 --- a/tests/Unit/UrlTest.php +++ b/tests/Unit/UrlTest.php @@ -5,17 +5,6 @@ use Tests\TestCase; class UrlTest extends TestCase { - public function test_request_url_takes_custom_url_into_account() - { - config()->set('app.url', 'http://example.com/bookstack'); - $this->get('/'); - $this->assertEquals('http://example.com/bookstack', request()->getUri()); - - config()->set('app.url', 'http://example.com/docs/content'); - $this->get('/'); - $this->assertEquals('http://example.com/docs/content', request()->getUri()); - } - public function test_url_helper_takes_custom_url_into_account() { $this->runWithEnv('APP_URL', 'http://example.com/bookstack', function() { From 9d7ce59b18c5cbeef017349f38f063a63b762188 Mon Sep 17 00:00:00 2001 From: benrubson <6764151+benrubson@users.noreply.github.com> Date: Sat, 23 May 2020 15:37:38 +0200 Subject: [PATCH 068/197] Move logFailedAccess into Activity --- app/Actions/ActivityService.php | 17 ++++++++++++++ app/Http/Controllers/Auth/LoginController.php | 22 +++---------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/app/Actions/ActivityService.php b/app/Actions/ActivityService.php index f56f1ca57..ca09aaef1 100644 --- a/app/Actions/ActivityService.php +++ b/app/Actions/ActivityService.php @@ -183,4 +183,21 @@ class ActivityService session()->flash('success', $message); } } + + /** + * Log failed accesses, for further processing by tools like Fail2Ban + * + * @param username + * @return void + */ + public function logFailedAccess($username) + { + $log_msg = config('logging.failed_access_message'); + + if (!is_string($username) || !is_string($log_msg) || strlen($log_msg)<1) + return; + + $log_msg = str_replace("%u", $username, $log_msg); + error_log($log_msg, 4); + } } diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index cf9e44e43..f5479814a 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -2,6 +2,7 @@ namespace BookStack\Http\Controllers\Auth; +use Activity; use BookStack\Auth\Access\SocialAuthService; use BookStack\Exceptions\LoginAttemptEmailNeededException; use BookStack\Exceptions\LoginAttemptException; @@ -102,7 +103,7 @@ class LoginController extends Controller $this->fireLockoutEvent($request); // Also log some error message - $this->logFailedAccess($request); + Activity::logFailedAccess($request->get($this->username())); return $this->sendLockoutResponse($request); } @@ -121,7 +122,7 @@ class LoginController extends Controller $this->incrementLoginAttempts($request); // Also log some error message - $this->logFailedAccess($request); + Activity::logFailedAccess($request->get($this->username())); return $this->sendFailedLoginResponse($request); } @@ -168,21 +169,4 @@ class LoginController extends Controller return redirect('/login'); } - /** - * Log failed accesses, for further processing by tools like Fail2Ban - * - * @param \Illuminate\Http\Request $request - * @return void - */ - protected function logFailedAccess($request) - { - $log_msg = config('logging.failed_access_message'); - - if (!is_string($request->get($this->username())) || !is_string($log_msg) || strlen($log_msg)<1) - return; - - $log_msg = str_replace("%u", $request->get($this->username()), $log_msg); - error_log($log_msg, 4); - } - } From 118e31608a987d2bfb7e4c81498b6a7cf0cac318 Mon Sep 17 00:00:00 2001 From: Honvid Date: Tue, 16 Jun 2020 11:44:08 +0800 Subject: [PATCH 069/197] fix the bug for lang's extra letter. --- resources/lang/zh_CN/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/zh_CN/settings.php b/resources/lang/zh_CN/settings.php index c2f015533..6a23b0906 100755 --- a/resources/lang/zh_CN/settings.php +++ b/resources/lang/zh_CN/settings.php @@ -57,7 +57,7 @@ return [ 'reg_enable_desc' => '启用注册后,用户将可以自己注册为站点用户。 注册后,他们将获得一个默认的单一用户角色。', 'reg_default_role' => '注册后的默认用户角色', 'reg_enable_external_warning' => '当启用外部LDAP或者SAML认证时,上面的选项会被忽略。当使用外部系统认证认证成功时,将自动创建非现有会员的用户账户。', - 'reg_email_confirmation' => '邮箱确认n', + 'reg_email_confirmation' => '邮箱确认', 'reg_email_confirmation_toggle' => '需要电子邮件确认', 'reg_confirm_email_desc' => '如果使用域名限制,则需要Email验证,并且该值将被忽略。', 'reg_confirm_restrict_domain' => '域名限制', From 76d02cd4725633c87c7885a319411a0671e814ae Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 24 Jun 2020 20:38:08 +0100 Subject: [PATCH 070/197] Started attempt at formalising component system used in BookStack Added a document to try to define things. Updated the loading so components are registed dynamically. Added some standardised ways to reference other elems & define options --- dev/docs/components.md | 56 +++++ resources/js/components/dropdown.js | 12 +- resources/js/components/index.js | 204 ++++++++++-------- resources/views/comments/comment.blade.php | 6 +- resources/views/common/header.blade.php | 6 +- resources/views/pages/form.blade.php | 15 +- resources/views/pages/revisions.blade.php | 12 +- .../partials/breadcrumb-listing.blade.php | 6 +- .../partials/entity-export-menu.blade.php | 6 +- resources/views/partials/sort.blade.php | 6 +- 10 files changed, 213 insertions(+), 116 deletions(-) create mode 100644 dev/docs/components.md diff --git a/dev/docs/components.md b/dev/docs/components.md new file mode 100644 index 000000000..2f59ae344 --- /dev/null +++ b/dev/docs/components.md @@ -0,0 +1,56 @@ +# JavaScript Components + +This document details the format for JavaScript components in BookStack. + +#### Defining a Component in JS + +```js +class Dropdown { + setup() { + } +} +``` + +#### Using a Component in HTML + +A component is used like so: + +```html +
    + + + +
    +``` + +The names will be parsed and new component instance will be created if a matching name is found in the `components/index.js` componentMapping. + +#### Element References + +Within a component you'll often need to refer to other element instances. This can be done like so: + +```html +
    + View more +
    +``` + +You can then access the span element as `this.$refs.toggle` in your component. + +#### Component Options + +```html +
    +
    +``` + +Will result with `this.$opts` being: + +```json +{ + "delay": "500", + "show": "" +} +``` \ No newline at end of file diff --git a/resources/js/components/dropdown.js b/resources/js/components/dropdown.js index 367c956ce..7b1ce3055 100644 --- a/resources/js/components/dropdown.js +++ b/resources/js/components/dropdown.js @@ -3,14 +3,16 @@ import {onSelect} from "../services/dom"; /** * Dropdown * Provides some simple logic to create simple dropdown menus. + * @extends {Component} */ class DropDown { - constructor(elem) { - this.container = elem; - this.menu = elem.querySelector('.dropdown-menu, [dropdown-menu]'); - this.moveMenu = elem.hasAttribute('dropdown-move-menu'); - this.toggle = elem.querySelector('[dropdown-toggle]'); + setup() { + this.container = this.$el; + this.menu = this.$refs.menu; + this.toggle = this.$refs.toggle; + this.moveMenu = this.$opts.moveMenu; + this.direction = (document.dir === 'rtl') ? 'right' : 'left'; this.body = document.body; this.showing = false; diff --git a/resources/js/components/index.js b/resources/js/components/index.js index 112827330..da194e438 100644 --- a/resources/js/components/index.js +++ b/resources/js/components/index.js @@ -1,109 +1,145 @@ -import dropdown from "./dropdown"; -import overlay from "./overlay"; -import backToTop from "./back-to-top"; -import notification from "./notification"; -import chapterToggle from "./chapter-toggle"; -import expandToggle from "./expand-toggle"; -import entitySelectorPopup from "./entity-selector-popup"; -import entitySelector from "./entity-selector"; -import sidebar from "./sidebar"; -import pagePicker from "./page-picker"; -import pageComments from "./page-comments"; -import wysiwygEditor from "./wysiwyg-editor"; -import markdownEditor from "./markdown-editor"; -import editorToolbox from "./editor-toolbox"; -import imagePicker from "./image-picker"; -import collapsible from "./collapsible"; -import toggleSwitch from "./toggle-switch"; -import pageDisplay from "./page-display"; -import shelfSort from "./shelf-sort"; -import homepageControl from "./homepage-control"; -import headerMobileToggle from "./header-mobile-toggle"; -import listSortControl from "./list-sort-control"; -import triLayout from "./tri-layout"; -import breadcrumbListing from "./breadcrumb-listing"; -import permissionsTable from "./permissions-table"; -import customCheckbox from "./custom-checkbox"; -import bookSort from "./book-sort"; -import settingAppColorPicker from "./setting-app-color-picker"; -import settingColorPicker from "./setting-color-picker"; -import entityPermissionsEditor from "./entity-permissions-editor"; -import templateManager from "./template-manager"; -import newUserPassword from "./new-user-password"; -import detailsHighlighter from "./details-highlighter"; -import codeHighlighter from "./code-highlighter"; +const componentMapping = {}; -const componentMapping = { - 'dropdown': dropdown, - 'overlay': overlay, - 'back-to-top': backToTop, - 'notification': notification, - 'chapter-toggle': chapterToggle, - 'expand-toggle': expandToggle, - 'entity-selector-popup': entitySelectorPopup, - 'entity-selector': entitySelector, - 'sidebar': sidebar, - 'page-picker': pagePicker, - 'page-comments': pageComments, - 'wysiwyg-editor': wysiwygEditor, - 'markdown-editor': markdownEditor, - 'editor-toolbox': editorToolbox, - 'image-picker': imagePicker, - 'collapsible': collapsible, - 'toggle-switch': toggleSwitch, - 'page-display': pageDisplay, - 'shelf-sort': shelfSort, - 'homepage-control': homepageControl, - 'header-mobile-toggle': headerMobileToggle, - 'list-sort-control': listSortControl, - 'tri-layout': triLayout, - 'breadcrumb-listing': breadcrumbListing, - 'permissions-table': permissionsTable, - 'custom-checkbox': customCheckbox, - 'book-sort': bookSort, - 'setting-app-color-picker': settingAppColorPicker, - 'setting-color-picker': settingColorPicker, - 'entity-permissions-editor': entityPermissionsEditor, - 'template-manager': templateManager, - 'new-user-password': newUserPassword, - 'details-highlighter': detailsHighlighter, - 'code-highlighter': codeHighlighter, -}; +const definitionFiles = require.context('./', false, /\.js$/); +for (const fileName of definitionFiles.keys()) { + const name = fileName.replace('./', '').split('.')[0]; + if (name !== 'index') { + componentMapping[name] = definitionFiles(fileName).default; + } +} window.components = {}; -const componentNames = Object.keys(componentMapping); - /** * Initialize components of the given name within the given element. * @param {String} componentName * @param {HTMLElement|Document} parentElement */ -function initComponent(componentName, parentElement) { - let elems = parentElement.querySelectorAll(`[${componentName}]`); - if (elems.length === 0) return; - - let component = componentMapping[componentName]; - if (typeof window.components[componentName] === "undefined") window.components[componentName] = []; +function searchForComponentInParent(componentName, parentElement) { + const elems = parentElement.querySelectorAll(`[${componentName}]`); for (let j = 0, jLen = elems.length; j < jLen; j++) { - let instance = new component(elems[j]); - if (typeof elems[j].components === 'undefined') elems[j].components = {}; - elems[j].components[componentName] = instance; - window.components[componentName].push(instance); + initComponent(componentName, elems[j]); } } +/** + * Initialize a component instance on the given dom element. + * @param {String} name + * @param {Element} element + */ +function initComponent(name, element) { + const componentModel = componentMapping[name]; + if (componentModel === undefined) return; + + // Create our component instance + let instance; + try { + instance = new componentModel(element); + instance.$el = element; + instance.$refs = parseRefs(name, element); + instance.$opts = parseOpts(name, element); + if (typeof instance.setup === 'function') { + instance.setup(); + } + } catch (e) { + console.error('Failed to create component', e, name, element); + } + + + // Add to global listing + if (typeof window.components[name] === "undefined") { + window.components[name] = []; + } + window.components[name].push(instance); + + // Add to element listing + if (typeof element.components === 'undefined') { + element.components = {}; + } + element.components[name] = instance; +} + +/** + * Parse out the element references within the given element + * for the given component name. + * @param {String} name + * @param {Element} element + */ +function parseRefs(name, element) { + const refs = {}; + const prefix = `${name}@` + const refElems = element.querySelectorAll(`[refs*="${prefix}"]`); + for (const el of refElems) { + const refNames = el.getAttribute('refs') + .split(' ') + .filter(str => str.startsWith(prefix)) + .map(str => str.replace(prefix, '')); + for (const ref of refNames) { + refs[ref] = el; + } + } + return refs; +} + +/** + * Parse out the element component options. + * @param {String} name + * @param {Element} element + * @return {Object} + */ +function parseOpts(name, element) { + const opts = {}; + const prefix = `option:${name}:`; + for (const {name, value} of element.attributes) { + if (name.startsWith(prefix)) { + const optName = name.replace(prefix, ''); + opts[kebabToCamel(optName)] = value || ''; + } + } + return opts; +} + +/** + * Convert a kebab-case string to camelCase + * @param {String} kebab + * @returns {string} + */ +function kebabToCamel(kebab) { + const ucFirst = (word) => word.slice(0,1).toUpperCase() + word.slice(1); + const words = kebab.split('-'); + return words[0] + words.slice(1).map(ucFirst).join(); +} + /** * Initialize all components found within the given element. * @param parentElement */ function initAll(parentElement) { if (typeof parentElement === 'undefined') parentElement = document; - for (let i = 0, len = componentNames.length; i < len; i++) { - initComponent(componentNames[i], parentElement); + + // Old attribute system + for (const componentName of Object.keys(componentMapping)) { + searchForComponentInParent(componentName, parentElement); + } + + // New component system + const componentElems = parentElement.querySelectorAll(`[component],[components]`); + + for (const el of componentElems) { + const componentNames = `${el.getAttribute('component') || ''} ${(el.getAttribute('components'))}`.toLowerCase().split(' ').filter(Boolean); + for (const name of componentNames) { + initComponent(name, el); + } } } window.components.init = initAll; export default initAll; + +/** + * @typedef Component + * @property {HTMLElement} $el + * @property {Object} $refs + * @property {Object} $opts + */ \ No newline at end of file diff --git a/resources/views/comments/comment.blade.php b/resources/views/comments/comment.blade.php index ea96a9250..322477ebd 100644 --- a/resources/views/comments/comment.blade.php +++ b/resources/views/comments/comment.blade.php @@ -27,9 +27,9 @@ @endif @if(userCan('comment-delete', $comment)) -