]> BookStack Code Mirror - bookstack/commitdiff
Merge branch 'development' into release
authorDan Brown <redacted>
Fri, 24 Jun 2022 10:45:29 +0000 (11:45 +0100)
committerDan Brown <redacted>
Fri, 24 Jun 2022 10:45:29 +0000 (11:45 +0100)
313 files changed:
.env.example.complete
.github/FUNDING.yml
.github/ISSUE_TEMPLATE/language_request.yml
.github/translators.txt
app/Actions/ActivityType.php
app/Actions/TagRepo.php
app/Auth/Access/GroupSyncService.php
app/Config/app.php
app/Config/auth.php
app/Config/session.php
app/Entities/Repos/BookRepo.php
app/Entities/Repos/BookshelfRepo.php
app/Entities/Repos/PageRepo.php
app/Entities/Tools/Cloner.php
app/Entities/Tools/ExportFormatter.php
app/Entities/Tools/HierarchyTransformer.php [new file with mode: 0644]
app/Entities/Tools/SearchIndex.php
app/Entities/Tools/TrashCan.php
app/Exceptions/Handler.php
app/Http/Controllers/Api/BookApiController.php
app/Http/Controllers/Api/BookExportApiController.php
app/Http/Controllers/Api/BookshelfApiController.php
app/Http/Controllers/Api/ChapterExportApiController.php
app/Http/Controllers/Api/PageExportApiController.php
app/Http/Controllers/AttachmentController.php
app/Http/Controllers/Auth/LoginController.php
app/Http/Controllers/BookController.php
app/Http/Controllers/BookExportController.php
app/Http/Controllers/BookshelfController.php
app/Http/Controllers/ChapterController.php
app/Http/Controllers/ChapterExportController.php
app/Http/Controllers/Controller.php
app/Http/Controllers/PageExportController.php
app/Http/Responses/DownloadResponseFactory.php [new file with mode: 0644]
app/Uploads/AttachmentService.php
app/Util/WebSafeMimeSniffer.php
composer.lock
database/factories/Auth/RoleFactory.php
dev/api/responses/books-list.json
dev/api/responses/books-update.json
dev/api/responses/shelves-list.json
dev/api/responses/shelves-update.json
package-lock.json
package.json
phpunit.xml
resources/icons/download.svg [new file with mode: 0644]
resources/js/code.mjs
resources/js/components/chapter-contents.js [new file with mode: 0644]
resources/js/components/chapter-toggle.js [deleted file]
resources/js/components/code-editor.js
resources/js/components/code-textarea.js [new file with mode: 0644]
resources/js/components/dropdown-search.js
resources/js/components/dropdown.js
resources/js/components/index.js
resources/js/components/markdown-editor.js
resources/js/services/animations.js
resources/js/services/vdom.js [new file with mode: 0644]
resources/js/wysiwyg/drop-paste-handling.js
resources/js/wysiwyg/plugin-codeeditor.js
resources/lang/ar/activities.php
resources/lang/ar/auth.php
resources/lang/ar/common.php
resources/lang/ar/entities.php
resources/lang/bg/activities.php
resources/lang/bg/auth.php
resources/lang/bg/common.php
resources/lang/bg/entities.php
resources/lang/bs/activities.php
resources/lang/bs/auth.php
resources/lang/bs/common.php
resources/lang/bs/entities.php
resources/lang/ca/activities.php
resources/lang/ca/auth.php
resources/lang/ca/common.php
resources/lang/ca/entities.php
resources/lang/cs/activities.php
resources/lang/cs/auth.php
resources/lang/cs/common.php
resources/lang/cs/entities.php
resources/lang/cy/activities.php [new file with mode: 0644]
resources/lang/cy/auth.php [new file with mode: 0644]
resources/lang/cy/common.php [new file with mode: 0644]
resources/lang/cy/components.php [new file with mode: 0644]
resources/lang/cy/editor.php [new file with mode: 0644]
resources/lang/cy/entities.php [new file with mode: 0644]
resources/lang/cy/errors.php [new file with mode: 0644]
resources/lang/cy/pagination.php [new file with mode: 0644]
resources/lang/cy/passwords.php [new file with mode: 0644]
resources/lang/cy/settings.php [new file with mode: 0644]
resources/lang/cy/validation.php [new file with mode: 0644]
resources/lang/da/activities.php
resources/lang/da/auth.php
resources/lang/da/common.php
resources/lang/da/editor.php
resources/lang/da/entities.php
resources/lang/da/settings.php
resources/lang/da/validation.php
resources/lang/de/activities.php
resources/lang/de/auth.php
resources/lang/de/common.php
resources/lang/de/entities.php
resources/lang/de/settings.php
resources/lang/de_informal/activities.php
resources/lang/de_informal/auth.php
resources/lang/de_informal/common.php
resources/lang/de_informal/entities.php
resources/lang/de_informal/settings.php
resources/lang/en/activities.php
resources/lang/en/auth.php
resources/lang/en/common.php
resources/lang/en/entities.php
resources/lang/es/activities.php
resources/lang/es/auth.php
resources/lang/es/common.php
resources/lang/es/entities.php
resources/lang/es_AR/activities.php
resources/lang/es_AR/auth.php
resources/lang/es_AR/common.php
resources/lang/es_AR/entities.php
resources/lang/es_AR/settings.php
resources/lang/et/activities.php
resources/lang/et/auth.php
resources/lang/et/common.php
resources/lang/et/entities.php
resources/lang/eu/activities.php
resources/lang/eu/auth.php
resources/lang/eu/common.php
resources/lang/eu/entities.php
resources/lang/fa/activities.php
resources/lang/fa/auth.php
resources/lang/fa/common.php
resources/lang/fa/entities.php
resources/lang/fr/activities.php
resources/lang/fr/auth.php
resources/lang/fr/common.php
resources/lang/fr/editor.php
resources/lang/fr/entities.php
resources/lang/fr/settings.php
resources/lang/he/activities.php
resources/lang/he/auth.php
resources/lang/he/common.php
resources/lang/he/entities.php
resources/lang/hr/activities.php
resources/lang/hr/auth.php
resources/lang/hr/common.php
resources/lang/hr/entities.php
resources/lang/hu/activities.php
resources/lang/hu/auth.php
resources/lang/hu/common.php
resources/lang/hu/entities.php
resources/lang/id/activities.php
resources/lang/id/auth.php
resources/lang/id/common.php
resources/lang/id/entities.php
resources/lang/it/activities.php
resources/lang/it/auth.php
resources/lang/it/common.php
resources/lang/it/entities.php
resources/lang/ja/activities.php
resources/lang/ja/auth.php
resources/lang/ja/common.php
resources/lang/ja/entities.php
resources/lang/ko/activities.php
resources/lang/ko/auth.php
resources/lang/ko/common.php
resources/lang/ko/entities.php
resources/lang/lt/activities.php
resources/lang/lt/auth.php
resources/lang/lt/common.php
resources/lang/lt/entities.php
resources/lang/lv/activities.php
resources/lang/lv/auth.php
resources/lang/lv/common.php
resources/lang/lv/entities.php
resources/lang/nb/activities.php
resources/lang/nb/auth.php
resources/lang/nb/common.php
resources/lang/nb/entities.php
resources/lang/nl/activities.php
resources/lang/nl/auth.php
resources/lang/nl/common.php
resources/lang/nl/entities.php
resources/lang/pl/activities.php
resources/lang/pl/auth.php
resources/lang/pl/common.php
resources/lang/pl/entities.php
resources/lang/pt/activities.php
resources/lang/pt/auth.php
resources/lang/pt/common.php
resources/lang/pt/entities.php
resources/lang/pt_BR/activities.php
resources/lang/pt_BR/auth.php
resources/lang/pt_BR/common.php
resources/lang/pt_BR/editor.php
resources/lang/pt_BR/entities.php
resources/lang/pt_BR/errors.php
resources/lang/pt_BR/settings.php
resources/lang/pt_BR/validation.php
resources/lang/ru/activities.php
resources/lang/ru/auth.php
resources/lang/ru/common.php
resources/lang/ru/entities.php
resources/lang/ru/settings.php
resources/lang/sk/activities.php
resources/lang/sk/auth.php
resources/lang/sk/common.php
resources/lang/sk/entities.php
resources/lang/sl/activities.php
resources/lang/sl/auth.php
resources/lang/sl/common.php
resources/lang/sl/entities.php
resources/lang/sv/activities.php
resources/lang/sv/auth.php
resources/lang/sv/common.php
resources/lang/sv/entities.php
resources/lang/tr/activities.php
resources/lang/tr/auth.php
resources/lang/tr/common.php
resources/lang/tr/entities.php
resources/lang/tr/settings.php
resources/lang/uk/activities.php
resources/lang/uk/auth.php
resources/lang/uk/common.php
resources/lang/uk/entities.php
resources/lang/uz/activities.php
resources/lang/uz/auth.php
resources/lang/uz/common.php
resources/lang/uz/entities.php
resources/lang/vi/activities.php
resources/lang/vi/auth.php
resources/lang/vi/common.php
resources/lang/vi/entities.php
resources/lang/vi/errors.php
resources/lang/vi/settings.php
resources/lang/zh_CN/activities.php
resources/lang/zh_CN/auth.php
resources/lang/zh_CN/common.php
resources/lang/zh_CN/entities.php
resources/lang/zh_TW/activities.php
resources/lang/zh_TW/auth.php
resources/lang/zh_TW/common.php
resources/lang/zh_TW/entities.php
resources/lang/zh_TW/settings.php
resources/sass/_blocks.scss
resources/sass/_buttons.scss
resources/sass/_components.scss
resources/sass/_forms.scss
resources/sass/_header.scss
resources/sass/_layout.scss
resources/sass/_lists.scss
resources/sass/_pages.scss
resources/sass/export-styles.scss
resources/sass/styles.scss
resources/views/attachments/list.blade.php
resources/views/auth/login-initiate.blade.php [new file with mode: 0644]
resources/views/books/edit.blade.php
resources/views/books/export.blade.php [deleted file]
resources/views/books/parts/convert-to-shelf.blade.php [new file with mode: 0644]
resources/views/books/show.blade.php
resources/views/chapters/edit.blade.php
resources/views/chapters/export.blade.php [deleted file]
resources/views/chapters/parts/child-menu.blade.php
resources/views/chapters/parts/convert-to-book.blade.php [new file with mode: 0644]
resources/views/chapters/parts/list-item.blade.php
resources/views/chapters/show.blade.php
resources/views/common/confirm-dialog.blade.php
resources/views/common/export-styles.blade.php [deleted file]
resources/views/common/header.blade.php
resources/views/entities/breadcrumb-listing.blade.php
resources/views/entities/export-menu.blade.php
resources/views/entities/meta.blade.php
resources/views/entities/selector-popup.blade.php
resources/views/exports/book.blade.php [new file with mode: 0644]
resources/views/exports/chapter.blade.php [new file with mode: 0644]
resources/views/exports/page.blade.php [moved from resources/views/pages/export.blade.php with 71% similarity]
resources/views/exports/parts/book-contents-menu.blade.php [new file with mode: 0644]
resources/views/exports/parts/chapter-contents-menu.blade.php [new file with mode: 0644]
resources/views/exports/parts/chapter-item.blade.php [new file with mode: 0644]
resources/views/exports/parts/custom-head.blade.php [moved from resources/views/common/export-custom-head.blade.php with 100% similarity]
resources/views/exports/parts/meta.blade.php [moved from resources/views/entities/export-meta.blade.php with 100% similarity]
resources/views/exports/parts/page-item.blade.php [new file with mode: 0644]
resources/views/exports/parts/styles.blade.php [new file with mode: 0644]
resources/views/form/entity-permissions.blade.php
resources/views/form/user-select.blade.php
resources/views/home/default.blade.php
resources/views/layouts/base.blade.php
resources/views/layouts/export.blade.php
resources/views/layouts/parts/base-body-end.blade.php [new file with mode: 0644]
resources/views/layouts/parts/base-body-start.blade.php [new file with mode: 0644]
resources/views/layouts/tri.blade.php
resources/views/pages/parts/code-editor.blade.php
resources/views/pages/parts/editor-toolbar.blade.php
resources/views/pages/parts/image-manager.blade.php
resources/views/pages/show.blade.php
resources/views/settings/audit.blade.php
resources/views/settings/customization.blade.php
resources/views/shelves/show.blade.php
resources/views/users/delete.blade.php
routes/web.php
tests/Api/BooksApiTest.php
tests/Api/ShelvesApiTest.php
tests/Auth/GroupSyncServiceTest.php [new file with mode: 0644]
tests/Auth/LoginAutoInitiateTest.php [new file with mode: 0644]
tests/Auth/MfaVerificationTest.php
tests/Entity/BookTest.php
tests/Entity/ConvertTest.php [new file with mode: 0644]
tests/Entity/EntitySearchTest.php
tests/Entity/ExportTest.php
tests/OpenGraphTest.php
tests/SharedTestHelpers.php
tests/TestResponse.php
tests/ThemeTest.php
version

index 0c7f8f6a5f5167647a0358789358e354f6f38296..c40ab1380ffd82f63294bd7493e47436d11acb20 100644 (file)
@@ -143,6 +143,10 @@ STORAGE_URL=false
 # Can be 'standard', 'ldap', 'saml2' or 'oidc'
 AUTH_METHOD=standard
 
+# Automatically initiate login via external auth system if it's the only auth method.
+# Works with saml2 or oidc auth methods.
+AUTH_AUTO_INITIATE=false
+
 # Social authentication configuration
 # All disabled by default.
 # Refer to https://www.bookstackapp.com/docs/admin/third-party-auth/
index 01b847186cf3b710a2209b35fb4a9e52029998c5..f3f51c7943cc7cdbca62f5bfcceff4942d534220 100644 (file)
@@ -1,3 +1,4 @@
 # These are supported funding model platforms
 
 github: [ssddanbrown]
+ko_fi: ssddanbrown
\ No newline at end of file
index 6f768cd74799f23d608e755110502cbe4971c64f..fad9ef1e83fb0e4bdf256ea57653bb9f89026dcb 100644 (file)
@@ -1,5 +1,5 @@
 name: Language Request
-description: Request a new language to be added to CrowdIn for you to translate
+description: Request a new language to be added to Crowdin for you to translate
 labels: [":earth_africa: Translations"]
 assignees:
   - ssddanbrown
@@ -23,7 +23,7 @@ body:
         This issue template is to request a new language be added to our [Crowdin translation management project](https://crowdin.com/project/bookstack).
         Please don't use this template to request a new language that you are not prepared to provide translations for.
       options:
-        - label: I confirm I'm offering to help translate for this new language via CrowdIn.
+        - label: I confirm I'm offering to help translate for this new language via Crowdin.
           required: true
   - type: markdown
     attributes:
index 7ba2ec112f4aacf8206c2c9358bee301f6e3414f..701de12001e6741b5f2c805d5364852916238beb 100644 (file)
@@ -243,3 +243,18 @@ Shukrullo (vodiylik) :: Uzbek
 William W. (Nevnt) :: Chinese Traditional
 eamaro :: Portuguese
 Ypsilon-dev :: Arabic
+Hieu Vuong Trung (vuongtrunghieu) :: Vietnamese
+David Clubb (davidoclubb) :: Welsh
+welles freire (wellesximenes) :: Portuguese, Brazilian
+Magnus Jensen (MagnusHJensen) :: Danish
+Hesley Magno (hesleymagno) :: Portuguese, Brazilian
+Éric Gaspar (erga) :: French
+Fr3shlama :: German
+DSR :: Spanish, Argentina
+Andrii Bodnar (andrii-bodnar) :: Ukrainian
+Younes el Anjri (younesea28) :: Dutch
+Guclu Ozturk (gucluoz) :: Turkish
+Atmis :: French
+redjack666 :: Chinese Traditional
+Ashita007 :: Russian
+lihaorr :: Chinese Simplified
index 8b5213a8b2af809f5e668f603a49d36f27dc1ecb..0ad25a5ab7210127442960ad2897b52ed7740bad 100644 (file)
@@ -16,11 +16,13 @@ class ActivityType
     const CHAPTER_MOVE = 'chapter_move';
 
     const BOOK_CREATE = 'book_create';
+    const BOOK_CREATE_FROM_CHAPTER = 'book_create_from_chapter';
     const BOOK_UPDATE = 'book_update';
     const BOOK_DELETE = 'book_delete';
     const BOOK_SORT = 'book_sort';
 
     const BOOKSHELF_CREATE = 'bookshelf_create';
+    const BOOKSHELF_CREATE_FROM_BOOK = 'bookshelf_create_from_book';
     const BOOKSHELF_UPDATE = 'bookshelf_update';
     const BOOKSHELF_DELETE = 'bookshelf_delete';
 
index 0acee7486b92a4dec062834799b99a406e6bba39..8cf1076019e6318785a3d5ed13fc8d4490b16517 100644 (file)
@@ -28,10 +28,10 @@ class TagRepo
                 'name',
                 ($searchTerm || $nameFilter) ? 'value' : DB::raw('COUNT(distinct value) as `values`'),
                 DB::raw('COUNT(id) as usages'),
-                DB::raw('SUM(IF(entity_type = \'BookStack\\\\Page\', 1, 0)) as page_count'),
-                DB::raw('SUM(IF(entity_type = \'BookStack\\\\Chapter\', 1, 0)) as chapter_count'),
-                DB::raw('SUM(IF(entity_type = \'BookStack\\\\Book\', 1, 0)) as book_count'),
-                DB::raw('SUM(IF(entity_type = \'BookStack\\\\BookShelf\', 1, 0)) as shelf_count'),
+                DB::raw('SUM(IF(entity_type = \'page\', 1, 0)) as page_count'),
+                DB::raw('SUM(IF(entity_type = \'chapter\', 1, 0)) as chapter_count'),
+                DB::raw('SUM(IF(entity_type = \'book\', 1, 0)) as book_count'),
+                DB::raw('SUM(IF(entity_type = \'bookshelf\', 1, 0)) as shelf_count'),
             ])
             ->orderBy($nameFilter ? 'value' : 'name');
 
index db19b007ac32b31f5a2bb6112514b6aa7b271826..74f0539d82ffcce72d8261be3e02ca6dcd2dddef 100644 (file)
@@ -28,10 +28,8 @@ class GroupSyncService
      */
     protected function externalIdMatchesGroupNames(string $externalId, array $groupNames): bool
     {
-        $externalAuthIds = explode(',', strtolower($externalId));
-
-        foreach ($externalAuthIds as $externalAuthId) {
-            if (in_array(trim($externalAuthId), $groupNames)) {
+        foreach ($this->parseRoleExternalAuthId($externalId) as $externalAuthId) {
+            if (in_array($externalAuthId, $groupNames)) {
                 return true;
             }
         }
@@ -39,6 +37,18 @@ class GroupSyncService
         return false;
     }
 
+    protected function parseRoleExternalAuthId(string $externalId): array
+    {
+        $inputIds = preg_split('/(?<!\\\),/', $externalId);
+        $cleanIds = [];
+
+        foreach ($inputIds as $inputId) {
+            $cleanIds[] = str_replace('\,', ',', trim($inputId));
+        }
+
+        return $cleanIds;
+    }
+
     /**
      * Match an array of group names to BookStack system roles.
      * Formats group names to be lower-case and hyphenated.
index 968addc69b4448048d5f4cb12417d2eb7efcc344..2b1de6f45e69aedb189da6343fd156981f50973c 100644 (file)
@@ -71,7 +71,7 @@ return [
     'locale' => env('APP_LANG', 'en'),
 
     // Locales available
-    'locales' => ['en', 'ar', 'bg', 'bs', 'ca', 'cs', 'da', 'de', 'de_informal', 'es', 'es_AR', 'et', 'eu', 'fa', 'fr', 'he', 'hr', 'hu', 'id', 'it', 'ja', 'ko', 'lt', 'lv', 'nl', 'nb', 'pt', 'pt_BR', 'sk', 'sl', 'sv', 'pl',  'ru', 'th', 'tr', 'uk', 'uz', 'vi', 'zh_CN', 'zh_TW'],
+    'locales' => ['en', 'ar', 'bg', 'bs', 'ca', 'cs', 'cy', 'da', 'de', 'de_informal', 'es', 'es_AR', 'et', 'eu', 'fa', 'fr', 'he', 'hr', 'hu', 'id', 'it', 'ja', 'ko', 'lt', 'lv', 'nl', 'nb', 'pt', 'pt_BR', 'sk', 'sl', 'sv', 'pl',  'ru', 'th', 'tr', 'uk', 'uz', 'vi', 'zh_CN', 'zh_TW'],
 
     //  Application Fallback Locale
     'fallback_locale' => 'en',
index 1e1a9d3507c737cf0ff7284cd52d97325620efac..37190156a96f13a70e2a3fe2c044797a2ed6f3fd 100644 (file)
@@ -13,6 +13,10 @@ return [
     // Options: standard, ldap, saml2, oidc
     'method' => env('AUTH_METHOD', 'standard'),
 
+    // Automatically initiate login via external auth system if it's the sole auth method.
+    // Works with saml2 or oidc auth methods.
+    'auto_initiate' => env('AUTH_AUTO_INITIATE', false),
+
     // Authentication Defaults
     // This option controls the default authentication "guard" and password
     // reset options for your application.
index 4bbb789010ff341a0cf6d6b505201412a5b76819..a00d758071201903b137d12d27a2581f7e481867 100644 (file)
@@ -72,7 +72,7 @@ return [
     // to the server if the browser has a HTTPS connection. This will keep
     // the cookie from being sent to you if it can not be done securely.
     'secure' => env('SESSION_SECURE_COOKIE', null)
-        ?? Str::startsWith(env('APP_URL'), 'https:'),
+        ?? Str::startsWith(env('APP_URL', ''), 'https:'),
 
     // HTTP Access Only
     // Setting this value to true will prevent JavaScript from accessing the
index 7c4b280a8ca2b6a2bd690f7adca54add1382f2a2..b5944fd460b2f23737e9c3ddcf22be005e72df4e 100644 (file)
@@ -91,6 +91,7 @@ class BookRepo
     {
         $book = new Book();
         $this->baseRepo->create($book, $input);
+        $this->baseRepo->updateCoverImage($book, $input['image'] ?? null);
         Activity::add(ActivityType::BOOK_CREATE, $book);
 
         return $book;
@@ -102,6 +103,11 @@ class BookRepo
     public function update(Book $book, array $input): Book
     {
         $this->baseRepo->update($book, $input);
+
+        if (array_key_exists('image', $input)) {
+            $this->baseRepo->updateCoverImage($book, $input['image'], $input['image'] === null);
+        }
+
         Activity::add(ActivityType::BOOK_UPDATE, $book);
 
         return $book;
index ceabba59af456e277b1f5fc49dedf90b11c02a1e..b85289b97d24d73ef7c3c17a5c9ab179c2114c62 100644 (file)
@@ -6,12 +6,10 @@ use BookStack\Actions\ActivityType;
 use BookStack\Entities\Models\Book;
 use BookStack\Entities\Models\Bookshelf;
 use BookStack\Entities\Tools\TrashCan;
-use BookStack\Exceptions\ImageUploadException;
 use BookStack\Exceptions\NotFoundException;
 use BookStack\Facades\Activity;
 use Exception;
 use Illuminate\Contracts\Pagination\LengthAwarePaginator;
-use Illuminate\Http\UploadedFile;
 use Illuminate\Support\Collection;
 
 class BookshelfRepo
@@ -89,6 +87,7 @@ class BookshelfRepo
     {
         $shelf = new Bookshelf();
         $this->baseRepo->create($shelf, $input);
+        $this->baseRepo->updateCoverImage($shelf, $input['image'] ?? null);
         $this->updateBooks($shelf, $bookIds);
         Activity::add(ActivityType::BOOKSHELF_CREATE, $shelf);
 
@@ -106,14 +105,17 @@ class BookshelfRepo
             $this->updateBooks($shelf, $bookIds);
         }
 
+        if (array_key_exists('image', $input)) {
+            $this->baseRepo->updateCoverImage($shelf, $input['image'], $input['image'] === null);
+        }
+
         Activity::add(ActivityType::BOOKSHELF_UPDATE, $shelf);
 
         return $shelf;
     }
 
     /**
-     * Update which books are assigned to this shelf by
-     * syncing the given book ids.
+     * Update which books are assigned to this shelf by syncing the given book ids.
      * Function ensures the books are visible to the current user and existing.
      */
     protected function updateBooks(Bookshelf $shelf, array $bookIds)
@@ -132,17 +134,6 @@ class BookshelfRepo
         $shelf->books()->sync($syncData);
     }
 
-    /**
-     * Update the given shelf cover image, or clear it.
-     *
-     * @throws ImageUploadException
-     * @throws Exception
-     */
-    public function updateCoverImage(Bookshelf $shelf, ?UploadedFile $coverImage, bool $removeImage = false)
-    {
-        $this->baseRepo->updateCoverImage($shelf, $coverImage, $removeImage);
-    }
-
     /**
      * Copy down the permissions of the given shelf to all child books.
      */
index c106d2fd30679d6f663cdd845ddbaf1b0aee4fe5..e3c6bd17af95b7ea869ffaa9c70ad059d248ee10 100644 (file)
@@ -392,23 +392,6 @@ class PageRepo
         return $parentClass::visible()->where('id', '=', $entityId)->first();
     }
 
-    /**
-     * Change the page's parent to the given entity.
-     */
-    protected function changeParent(Page $page, Entity $parent)
-    {
-        $book = ($parent instanceof Chapter) ? $parent->book : $parent;
-        $page->chapter_id = ($parent instanceof Chapter) ? $parent->id : 0;
-        $page->save();
-
-        if ($page->book->id !== $book->id) {
-            $page->changeBook($book->id);
-        }
-
-        $page->load('book');
-        $book->rebuildPermissions();
-    }
-
     /**
      * Get a page revision to update for the given page.
      * Checks for an existing revisions before providing a fresh one.
index b4923b90aac1f0048c044b2cc374a8cb25b8f7b9..92b62a7547a7422785d09b7c4317d31cec9ec19a 100644 (file)
@@ -16,25 +16,10 @@ use Illuminate\Http\UploadedFile;
 
 class Cloner
 {
-    /**
-     * @var PageRepo
-     */
-    protected $pageRepo;
-
-    /**
-     * @var ChapterRepo
-     */
-    protected $chapterRepo;
-
-    /**
-     * @var BookRepo
-     */
-    protected $bookRepo;
-
-    /**
-     * @var ImageService
-     */
-    protected $imageService;
+    protected PageRepo $pageRepo;
+    protected ChapterRepo $chapterRepo;
+    protected BookRepo $bookRepo;
+    protected ImageService $imageService;
 
     public function __construct(PageRepo $pageRepo, ChapterRepo $chapterRepo, BookRepo $bookRepo, ImageService $imageService)
     {
@@ -50,11 +35,8 @@ class Cloner
     public function clonePage(Page $original, Entity $parent, string $newName): Page
     {
         $copyPage = $this->pageRepo->getNewDraftPage($parent);
-        $pageData = $original->getAttributes();
-
-        // Update name & tags
+        $pageData = $this->entityToInputData($original);
         $pageData['name'] = $newName;
-        $pageData['tags'] = $this->entityTagsToInputArray($original);
 
         return $this->pageRepo->publishDraft($copyPage, $pageData);
     }
@@ -65,9 +47,8 @@ class Cloner
      */
     public function cloneChapter(Chapter $original, Book $parent, string $newName): Chapter
     {
-        $chapterDetails = $original->getAttributes();
+        $chapterDetails = $this->entityToInputData($original);
         $chapterDetails['name'] = $newName;
-        $chapterDetails['tags'] = $this->entityTagsToInputArray($original);
 
         $copyChapter = $this->chapterRepo->create($chapterDetails, $parent);
 
@@ -87,9 +68,8 @@ class Cloner
      */
     public function cloneBook(Book $original, string $newName): Book
     {
-        $bookDetails = $original->getAttributes();
+        $bookDetails = $this->entityToInputData($original);
         $bookDetails['name'] = $newName;
-        $bookDetails['tags'] = $this->entityTagsToInputArray($original);
 
         $copyBook = $this->bookRepo->create($bookDetails);
 
@@ -104,26 +84,48 @@ class Cloner
             }
         }
 
-        if ($original->cover) {
-            try {
-                $tmpImgFile = tmpfile();
-                $uploadedFile = $this->imageToUploadedFile($original->cover, $tmpImgFile);
-                $this->bookRepo->updateCoverImage($copyBook, $uploadedFile, false);
-            } catch (\Exception $exception) {
-            }
+        return $copyBook;
+    }
+
+    /**
+     * Convert an entity to a raw data array of input data.
+     *
+     * @return array<string, mixed>
+     */
+    public function entityToInputData(Entity $entity): array
+    {
+        $inputData = $entity->getAttributes();
+        $inputData['tags'] = $this->entityTagsToInputArray($entity);
+
+        // Add a cover to the data if existing on the original entity
+        if ($entity->cover instanceof Image) {
+            $uploadedFile = $this->imageToUploadedFile($entity->cover);
+            $inputData['image'] = $uploadedFile;
         }
 
-        return $copyBook;
+        return $inputData;
+    }
+
+    /**
+     * Copy the permission settings from the source entity to the target entity.
+     */
+    public function copyEntityPermissions(Entity $sourceEntity, Entity $targetEntity): void
+    {
+        $targetEntity->restricted = $sourceEntity->restricted;
+        $permissions = $sourceEntity->permissions()->get(['role_id', 'action'])->toArray();
+        $targetEntity->permissions()->delete();
+        $targetEntity->permissions()->createMany($permissions);
+        $targetEntity->rebuildPermissions();
     }
 
     /**
      * Convert an image instance to an UploadedFile instance to mimic
      * a file being uploaded.
      */
-    protected function imageToUploadedFile(Image $image, &$tmpFile): ?UploadedFile
+    protected function imageToUploadedFile(Image $image): ?UploadedFile
     {
         $imgData = $this->imageService->getImageData($image);
-        $tmpImgFilePath = stream_get_meta_data($tmpFile)['uri'];
+        $tmpImgFilePath = tempnam(sys_get_temp_dir(), 'bs_cover_clone_');
         file_put_contents($tmpImgFilePath, $imgData);
 
         return new UploadedFile($tmpImgFilePath, basename($image->path));
index 99aa4536f52bef1ec985c2b46aace5ed5c0f2669..97902db8219c12d5183a97b0e5a3565d4c158378 100644 (file)
@@ -39,7 +39,7 @@ class ExportFormatter
     public function pageToContainedHtml(Page $page)
     {
         $page->html = (new PageContent($page))->render();
-        $pageHtml = view('pages.export', [
+        $pageHtml = view('exports.page', [
             'page'       => $page,
             'format'     => 'html',
             'cspContent' => $this->cspService->getCspMetaTagValue(),
@@ -59,7 +59,7 @@ class ExportFormatter
         $pages->each(function ($page) {
             $page->html = (new PageContent($page))->render();
         });
-        $html = view('chapters.export', [
+        $html = view('exports.chapter', [
             'chapter'    => $chapter,
             'pages'      => $pages,
             'format'     => 'html',
@@ -77,7 +77,7 @@ class ExportFormatter
     public function bookToContainedHtml(Book $book)
     {
         $bookTree = (new BookContents($book))->getTree(false, true);
-        $html = view('books.export', [
+        $html = view('exports.book', [
             'book'         => $book,
             'bookChildren' => $bookTree,
             'format'       => 'html',
@@ -95,7 +95,7 @@ class ExportFormatter
     public function pageToPdf(Page $page)
     {
         $page->html = (new PageContent($page))->render();
-        $html = view('pages.export', [
+        $html = view('exports.page', [
             'page'   => $page,
             'format' => 'pdf',
             'engine' => $this->pdfGenerator->getActiveEngine(),
@@ -116,7 +116,7 @@ class ExportFormatter
             $page->html = (new PageContent($page))->render();
         });
 
-        $html = view('chapters.export', [
+        $html = view('exports.chapter', [
             'chapter' => $chapter,
             'pages'   => $pages,
             'format'  => 'pdf',
@@ -134,7 +134,7 @@ class ExportFormatter
     public function bookToPdf(Book $book)
     {
         $bookTree = (new BookContents($book))->getTree(false, true);
-        $html = view('books.export', [
+        $html = view('exports.book', [
             'book'         => $book,
             'bookChildren' => $bookTree,
             'format'       => 'pdf',
diff --git a/app/Entities/Tools/HierarchyTransformer.php b/app/Entities/Tools/HierarchyTransformer.php
new file mode 100644 (file)
index 0000000..50d9e2e
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+
+namespace BookStack\Entities\Tools;
+
+use BookStack\Actions\ActivityType;
+use BookStack\Entities\Models\Book;
+use BookStack\Entities\Models\Bookshelf;
+use BookStack\Entities\Models\Chapter;
+use BookStack\Entities\Models\Page;
+use BookStack\Entities\Repos\BookRepo;
+use BookStack\Entities\Repos\BookshelfRepo;
+use BookStack\Facades\Activity;
+
+class HierarchyTransformer
+{
+    protected BookRepo $bookRepo;
+    protected BookshelfRepo $shelfRepo;
+    protected Cloner $cloner;
+    protected TrashCan $trashCan;
+
+    public function __construct(BookRepo $bookRepo, BookshelfRepo $shelfRepo, Cloner $cloner, TrashCan $trashCan)
+    {
+        $this->bookRepo = $bookRepo;
+        $this->shelfRepo = $shelfRepo;
+        $this->cloner = $cloner;
+        $this->trashCan = $trashCan;
+    }
+
+    /**
+     * Transform a chapter into a book.
+     * Does not check permissions, check before calling.
+     */
+    public function transformChapterToBook(Chapter $chapter): Book
+    {
+        $inputData = $this->cloner->entityToInputData($chapter);
+        $book = $this->bookRepo->create($inputData);
+        $this->cloner->copyEntityPermissions($chapter, $book);
+
+        /** @var Page $page */
+        foreach ($chapter->pages as $page) {
+            $page->chapter_id = 0;
+            $page->changeBook($book->id);
+        }
+
+        $this->trashCan->destroyEntity($chapter);
+
+        Activity::add(ActivityType::BOOK_CREATE_FROM_CHAPTER, $book);
+
+        return $book;
+    }
+
+    /**
+     * Transform a book into a shelf.
+     * Does not check permissions, check before calling.
+     */
+    public function transformBookToShelf(Book $book): Bookshelf
+    {
+        $inputData = $this->cloner->entityToInputData($book);
+        $shelf = $this->shelfRepo->create($inputData, []);
+        $this->cloner->copyEntityPermissions($book, $shelf);
+
+        $shelfBookSyncData = [];
+
+        /** @var Chapter $chapter */
+        foreach ($book->chapters as $index => $chapter) {
+            $newBook = $this->transformChapterToBook($chapter);
+            $shelfBookSyncData[$newBook->id] = ['order' => $index];
+            if (!$newBook->restricted) {
+                $this->cloner->copyEntityPermissions($shelf, $newBook);
+            }
+        }
+
+        if ($book->directPages->count() > 0) {
+            $book->name .= ' ' . trans('entities.pages');
+            $shelfBookSyncData[$book->id] = ['order' => count($shelfBookSyncData) + 1];
+            $book->save();
+        } else {
+            $this->trashCan->destroyEntity($book);
+        }
+
+        $shelf->books()->sync($shelfBookSyncData);
+
+        Activity::add(ActivityType::BOOKSHELF_CREATE_FROM_BOOK, $shelf);
+
+        return $shelf;
+    }
+}
index d43d982079d88262280dbe9c70b40d11632d0577..db44daadfb931122e2a449c9ab3078bf1974877d 100644 (file)
@@ -147,6 +147,8 @@ class SearchIndex
         ];
 
         $html = '<body>' . $html . '</body>';
+        $html = str_ireplace(['<br>', '<br />', '<br/>'], "\n", $html);
+
         libxml_use_internal_errors(true);
         $doc = new DOMDocument();
         $doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
index 1e130c9e17956cc8ecaf8db05a4d3d9807d5c67b..abec2e2d57a0fb1a67f3fa08a97e7ea58c050d8a 100644 (file)
@@ -344,7 +344,7 @@ class TrashCan
      *
      * @throws Exception
      */
-    protected function destroyEntity(Entity $entity): int
+    public function destroyEntity(Entity $entity): int
     {
         if ($entity instanceof Page) {
             return $this->destroyPage($entity);
index 317b011d87de92f3369d7b1b3a993efacdd1c864..187664f9ef7cf779c9f7e85321975e176f789d42 100644 (file)
@@ -21,6 +21,7 @@ class Handler extends ExceptionHandler
      */
     protected $dontReport = [
         NotFoundException::class,
+        StoppedAuthenticationException::class,
     ];
 
     /**
index b28e3eefa3af93802c894bfd8436d41176bf0702..15565c361f2ed6f3076a6dae6da92650c27f9901 100644 (file)
@@ -11,19 +11,6 @@ class BookApiController extends ApiController
 {
     protected $bookRepo;
 
-    protected $rules = [
-        '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'],
-        ],
-    ];
-
     public function __construct(BookRepo $bookRepo)
     {
         $this->bookRepo = $bookRepo;
@@ -37,19 +24,21 @@ class BookApiController extends ApiController
         $books = Book::visible();
 
         return $this->apiListingResponse($books, [
-            'id', 'name', 'slug', 'description', 'created_at', 'updated_at', 'created_by', 'updated_by', 'owned_by', 'image_id',
+            'id', 'name', 'slug', 'description', 'created_at', 'updated_at', 'created_by', 'updated_by', 'owned_by',
         ]);
     }
 
     /**
      * Create a new book in the system.
+     * The cover image of a book can be set by sending a file via an 'image' property within a 'multipart/form-data' request.
+     * If the 'image' property is null then the book cover image will be removed.
      *
      * @throws ValidationException
      */
     public function create(Request $request)
     {
         $this->checkPermission('book-create-all');
-        $requestData = $this->validate($request, $this->rules['create']);
+        $requestData = $this->validate($request, $this->rules()['create']);
 
         $book = $this->bookRepo->create($requestData);
 
@@ -68,6 +57,8 @@ class BookApiController extends ApiController
 
     /**
      * Update the details of a single book.
+     * The cover image of a book can be set by sending a file via an 'image' property within a 'multipart/form-data' request.
+     * If the 'image' property is null then the book cover image will be removed.
      *
      * @throws ValidationException
      */
@@ -76,7 +67,7 @@ class BookApiController extends ApiController
         $book = Book::visible()->findOrFail($id);
         $this->checkOwnablePermission('book-update', $book);
 
-        $requestData = $this->validate($request, $this->rules['update']);
+        $requestData = $this->validate($request, $this->rules()['update']);
         $book = $this->bookRepo->update($book, $requestData);
 
         return response()->json($book);
@@ -97,4 +88,22 @@ class BookApiController extends ApiController
 
         return response('', 204);
     }
+
+    protected function rules(): array
+    {
+        return [
+            'create' => [
+                'name'        => ['required', 'string', 'max:255'],
+                'description' => ['string', 'max:1000'],
+                'tags'        => ['array'],
+                'image'       => array_merge(['nullable'], $this->getImageValidationRules()),
+            ],
+            'update' => [
+                'name'        => ['string', 'min:1', 'max:255'],
+                'description' => ['string', 'max:1000'],
+                'tags'        => ['array'],
+                'image'       => array_merge(['nullable'], $this->getImageValidationRules()),
+            ],
+        ];
+    }
 }
index 028bc3a817ebf726b358ca0f7b8d47f393695bf8..84090befba53249284e267bf77d767d88888cecb 100644 (file)
@@ -26,7 +26,7 @@ class BookExportApiController extends ApiController
         $book = Book::visible()->findOrFail($id);
         $pdfContent = $this->exportFormatter->bookToPdf($book);
 
-        return $this->downloadResponse($pdfContent, $book->slug . '.pdf');
+        return $this->download()->directly($pdfContent, $book->slug . '.pdf');
     }
 
     /**
@@ -39,7 +39,7 @@ class BookExportApiController extends ApiController
         $book = Book::visible()->findOrFail($id);
         $htmlContent = $this->exportFormatter->bookToContainedHtml($book);
 
-        return $this->downloadResponse($htmlContent, $book->slug . '.html');
+        return $this->download()->directly($htmlContent, $book->slug . '.html');
     }
 
     /**
@@ -50,7 +50,7 @@ class BookExportApiController extends ApiController
         $book = Book::visible()->findOrFail($id);
         $textContent = $this->exportFormatter->bookToPlainText($book);
 
-        return $this->downloadResponse($textContent, $book->slug . '.txt');
+        return $this->download()->directly($textContent, $book->slug . '.txt');
     }
 
     /**
@@ -61,6 +61,6 @@ class BookExportApiController extends ApiController
         $book = Book::visible()->findOrFail($id);
         $markdown = $this->exportFormatter->bookToMarkdown($book);
 
-        return $this->downloadResponse($markdown, $book->slug . '.md');
+        return $this->download()->directly($markdown, $book->slug . '.md');
     }
 }
index 63275a72a66191fb9880c425629cbc99126ddf65..620df1638f903c9d1f39e41648866c570f5fb069 100644 (file)
@@ -13,21 +13,6 @@ class BookshelfApiController extends ApiController
 {
     protected BookshelfRepo $bookshelfRepo;
 
-    protected $rules = [
-        'create' => [
-            'name'        => ['required', 'string', 'max:255'],
-            'description' => ['string', 'max:1000'],
-            'books'       => ['array'],
-            'tags'        => ['array'],
-        ],
-        'update' => [
-            'name'        => ['string', 'min:1', 'max:255'],
-            'description' => ['string', 'max:1000'],
-            'books'       => ['array'],
-            'tags'        => ['array'],
-        ],
-    ];
-
     /**
      * BookshelfApiController constructor.
      */
@@ -44,7 +29,7 @@ class BookshelfApiController extends ApiController
         $shelves = Bookshelf::visible();
 
         return $this->apiListingResponse($shelves, [
-            'id', 'name', 'slug', 'description', 'created_at', 'updated_at', 'created_by', 'updated_by', 'owned_by', 'image_id',
+            'id', 'name', 'slug', 'description', 'created_at', 'updated_at', 'created_by', 'updated_by', 'owned_by',
         ]);
     }
 
@@ -52,13 +37,15 @@ 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.
+     * The cover image of a shelf can be set by sending a file via an 'image' property within a 'multipart/form-data' request.
+     * If the 'image' property is null then the shelf cover image will be removed.
      *
      * @throws ValidationException
      */
     public function create(Request $request)
     {
         $this->checkPermission('bookshelf-create-all');
-        $requestData = $this->validate($request, $this->rules['create']);
+        $requestData = $this->validate($request, $this->rules()['create']);
 
         $bookIds = $request->get('books', []);
         $shelf = $this->bookshelfRepo->create($requestData, $bookIds);
@@ -86,6 +73,8 @@ class BookshelfApiController extends ApiController
      * 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.
+     * The cover image of a shelf can be set by sending a file via an 'image' property within a 'multipart/form-data' request.
+     * If the 'image' property is null then the shelf cover image will be removed.
      *
      * @throws ValidationException
      */
@@ -94,7 +83,7 @@ class BookshelfApiController extends ApiController
         $shelf = Bookshelf::visible()->findOrFail($id);
         $this->checkOwnablePermission('bookshelf-update', $shelf);
 
-        $requestData = $this->validate($request, $this->rules['update']);
+        $requestData = $this->validate($request, $this->rules()['update']);
         $bookIds = $request->get('books', null);
 
         $shelf = $this->bookshelfRepo->update($shelf, $requestData, $bookIds);
@@ -117,4 +106,24 @@ class BookshelfApiController extends ApiController
 
         return response('', 204);
     }
+
+    protected function rules(): array
+    {
+        return [
+            'create' => [
+                'name'        => ['required', 'string', 'max:255'],
+                'description' => ['string', 'max:1000'],
+                'books'       => ['array'],
+                'tags'        => ['array'],
+                'image'       => array_merge(['nullable'], $this->getImageValidationRules()),
+            ],
+            'update' => [
+                'name'        => ['string', 'min:1', 'max:255'],
+                'description' => ['string', 'max:1000'],
+                'books'       => ['array'],
+                'tags'        => ['array'],
+                'image'       => array_merge(['nullable'], $this->getImageValidationRules()),
+            ],
+        ];
+    }
 }
index 5715ab2e37c6c9f7e682ad69b407f27153e3934e..faf5d812e207c667170fd8c361f4a976ee3d7f11 100644 (file)
@@ -29,7 +29,7 @@ class ChapterExportApiController extends ApiController
         $chapter = Chapter::visible()->findOrFail($id);
         $pdfContent = $this->exportFormatter->chapterToPdf($chapter);
 
-        return $this->downloadResponse($pdfContent, $chapter->slug . '.pdf');
+        return $this->download()->directly($pdfContent, $chapter->slug . '.pdf');
     }
 
     /**
@@ -42,7 +42,7 @@ class ChapterExportApiController extends ApiController
         $chapter = Chapter::visible()->findOrFail($id);
         $htmlContent = $this->exportFormatter->chapterToContainedHtml($chapter);
 
-        return $this->downloadResponse($htmlContent, $chapter->slug . '.html');
+        return $this->download()->directly($htmlContent, $chapter->slug . '.html');
     }
 
     /**
@@ -53,7 +53,7 @@ class ChapterExportApiController extends ApiController
         $chapter = Chapter::visible()->findOrFail($id);
         $textContent = $this->exportFormatter->chapterToPlainText($chapter);
 
-        return $this->downloadResponse($textContent, $chapter->slug . '.txt');
+        return $this->download()->directly($textContent, $chapter->slug . '.txt');
     }
 
     /**
@@ -64,6 +64,6 @@ class ChapterExportApiController extends ApiController
         $chapter = Chapter::visible()->findOrFail($id);
         $markdown = $this->exportFormatter->chapterToMarkdown($chapter);
 
-        return $this->downloadResponse($markdown, $chapter->slug . '.md');
+        return $this->download()->directly($markdown, $chapter->slug . '.md');
     }
 }
index ce5700c79b9add01a9b2eb8d418f5b3a785344e8..f2edffba3d8b8934175705ada9a4327d2d0724b4 100644 (file)
@@ -26,7 +26,7 @@ class PageExportApiController extends ApiController
         $page = Page::visible()->findOrFail($id);
         $pdfContent = $this->exportFormatter->pageToPdf($page);
 
-        return $this->downloadResponse($pdfContent, $page->slug . '.pdf');
+        return $this->download()->directly($pdfContent, $page->slug . '.pdf');
     }
 
     /**
@@ -39,7 +39,7 @@ class PageExportApiController extends ApiController
         $page = Page::visible()->findOrFail($id);
         $htmlContent = $this->exportFormatter->pageToContainedHtml($page);
 
-        return $this->downloadResponse($htmlContent, $page->slug . '.html');
+        return $this->download()->directly($htmlContent, $page->slug . '.html');
     }
 
     /**
@@ -50,7 +50,7 @@ class PageExportApiController extends ApiController
         $page = Page::visible()->findOrFail($id);
         $textContent = $this->exportFormatter->pageToPlainText($page);
 
-        return $this->downloadResponse($textContent, $page->slug . '.txt');
+        return $this->download()->directly($textContent, $page->slug . '.txt');
     }
 
     /**
@@ -61,6 +61,6 @@ class PageExportApiController extends ApiController
         $page = Page::visible()->findOrFail($id);
         $markdown = $this->exportFormatter->pageToMarkdown($page);
 
-        return $this->downloadResponse($markdown, $page->slug . '.md');
+        return $this->download()->directly($markdown, $page->slug . '.md');
     }
 }
index 0a092b63ae11385e4d67dae6218109b2e2f659fa..03e362f4a78f273573195d120ae806a9d65931ae 100644 (file)
@@ -233,10 +233,10 @@ class AttachmentController extends Controller
         $attachmentStream = $this->attachmentService->streamAttachmentFromStorage($attachment);
 
         if ($request->get('open') === 'true') {
-            return $this->streamedInlineDownloadResponse($attachmentStream, $fileName);
+            return $this->download()->streamedInline($attachmentStream, $fileName);
         }
 
-        return $this->streamedDownloadResponse($attachmentStream, $fileName);
+        return $this->download()->streamedDirectly($attachmentStream, $fileName);
     }
 
     /**
index 742e1047284403518e8b3ac73cb081c560be945b..f1a1a8bd6930bbc2cbf5f6b1e0f268d9dfefcaa5 100644 (file)
@@ -25,17 +25,16 @@ class LoginController extends Controller
     |
     */
 
-    use AuthenticatesUsers;
+    use AuthenticatesUsers { logout as traitLogout; }
 
     /**
      * Redirection paths.
      */
     protected $redirectTo = '/';
     protected $redirectPath = '/';
-    protected $redirectAfterLogout = '/login';
 
-    protected $socialAuthService;
-    protected $loginService;
+    protected SocialAuthService $socialAuthService;
+    protected LoginService $loginService;
 
     /**
      * Create a new controller instance.
@@ -50,7 +49,6 @@ class LoginController extends Controller
         $this->loginService = $loginService;
 
         $this->redirectPath = url('/');
-        $this->redirectAfterLogout = url('/login');
     }
 
     public function username()
@@ -73,6 +71,7 @@ class LoginController extends Controller
     {
         $socialDrivers = $this->socialAuthService->getActiveDrivers();
         $authMethod = config('auth.method');
+        $preventInitiation = $request->get('prevent_auto_init') === 'true';
 
         if ($request->has('email')) {
             session()->flashInput([
@@ -84,6 +83,12 @@ class LoginController extends Controller
         // Store the previous location for redirect after login
         $this->updateIntendedFromPrevious();
 
+        if (!$preventInitiation && $this->shouldAutoInitiate()) {
+            return view('auth.login-initiate', [
+                'authMethod'    => $authMethod,
+            ]);
+        }
+
         return view('auth.login', [
             'socialDrivers' => $socialDrivers,
             'authMethod'    => $authMethod,
@@ -251,4 +256,32 @@ class LoginController extends Controller
 
         redirect()->setIntendedUrl($previous);
     }
+
+    /**
+     * Check if login auto-initiate should be valid based upon authentication config.
+     */
+    protected function shouldAutoInitiate(): bool
+    {
+        $socialDrivers = $this->socialAuthService->getActiveDrivers();
+        $authMethod = config('auth.method');
+        $autoRedirect = config('auth.auto_initiate');
+
+        return $autoRedirect && count($socialDrivers) === 0 && in_array($authMethod, ['oidc', 'saml2']);
+    }
+
+    /**
+     * Logout user and perform subsequent redirect.
+     *
+     * @param \Illuminate\Http\Request $request
+     *
+     * @return mixed
+     */
+    public function logout(Request $request)
+    {
+        $this->traitLogout($request);
+
+        $redirectUri = $this->shouldAutoInitiate() ? '/login?prevent_auto_init=true' : '/';
+
+        return redirect($redirectUri);
+    }
 }
index bc403c6d04495eaf1adf28d4895b9b7f9c6bfeab..681ed96bb7cfd4bfb2afcd520e6f005956c7f59d 100644 (file)
@@ -9,6 +9,7 @@ use BookStack\Entities\Models\Bookshelf;
 use BookStack\Entities\Repos\BookRepo;
 use BookStack\Entities\Tools\BookContents;
 use BookStack\Entities\Tools\Cloner;
+use BookStack\Entities\Tools\HierarchyTransformer;
 use BookStack\Entities\Tools\PermissionsUpdater;
 use BookStack\Entities\Tools\ShelfContext;
 use BookStack\Exceptions\ImageUploadException;
@@ -100,7 +101,6 @@ class BookController extends Controller
         }
 
         $book = $this->bookRepo->create($request->all());
-        $this->bookRepo->updateCoverImage($book, $request->file('image', null));
 
         if ($bookshelf) {
             $bookshelf->appendBook($book);
@@ -158,15 +158,20 @@ class BookController extends Controller
     {
         $book = $this->bookRepo->getBySlug($slug);
         $this->checkOwnablePermission('book-update', $book);
-        $this->validate($request, [
+
+        $validated = $this->validate($request, [
             'name'        => ['required', 'string', 'max:255'],
             'description' => ['string', 'max:1000'],
             'image'       => array_merge(['nullable'], $this->getImageValidationRules()),
         ]);
 
-        $book = $this->bookRepo->update($book, $request->all());
-        $resetCover = $request->has('image_reset');
-        $this->bookRepo->updateCoverImage($book, $request->file('image', null), $resetCover);
+        if ($request->has('image_reset')) {
+            $validated['image'] = null;
+        } elseif (array_key_exists('image', $validated) && is_null($validated['image'])) {
+            unset($validated['image']);
+        }
+
+        $book = $this->bookRepo->update($book, $validated);
 
         return redirect($book->getUrl());
     }
@@ -262,4 +267,20 @@ class BookController extends Controller
 
         return redirect($bookCopy->getUrl());
     }
+
+    /**
+     * Convert the chapter to a book.
+     */
+    public function convertToShelf(HierarchyTransformer $transformer, string $bookSlug)
+    {
+        $book = $this->bookRepo->getBySlug($bookSlug);
+        $this->checkOwnablePermission('book-update', $book);
+        $this->checkOwnablePermission('book-delete', $book);
+        $this->checkPermission('bookshelf-create-all');
+        $this->checkPermission('book-create-all');
+
+        $shelf = $transformer->transformBookToShelf($book);
+
+        return redirect($shelf->getUrl());
+    }
 }
index 7f6dd801752b5e3901cb6188e3dc200888f32984..cc8d48a35511e5c6504c69b33512c9164fd22793 100644 (file)
@@ -31,7 +31,7 @@ class BookExportController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $pdfContent = $this->exportFormatter->bookToPdf($book);
 
-        return $this->downloadResponse($pdfContent, $bookSlug . '.pdf');
+        return $this->download()->directly($pdfContent, $bookSlug . '.pdf');
     }
 
     /**
@@ -44,7 +44,7 @@ class BookExportController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $htmlContent = $this->exportFormatter->bookToContainedHtml($book);
 
-        return $this->downloadResponse($htmlContent, $bookSlug . '.html');
+        return $this->download()->directly($htmlContent, $bookSlug . '.html');
     }
 
     /**
@@ -55,7 +55,7 @@ class BookExportController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $textContent = $this->exportFormatter->bookToPlainText($book);
 
-        return $this->downloadResponse($textContent, $bookSlug . '.txt');
+        return $this->download()->directly($textContent, $bookSlug . '.txt');
     }
 
     /**
@@ -66,6 +66,6 @@ class BookExportController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $textContent = $this->exportFormatter->bookToMarkdown($book);
 
-        return $this->downloadResponse($textContent, $bookSlug . '.md');
+        return $this->download()->directly($textContent, $bookSlug . '.md');
     }
 }
index 9a7f78a85a0417fc70b3ea707ea495397577e1eb..a294bf7318c2a35a44d42ff3772b15f900a5123d 100644 (file)
@@ -83,15 +83,15 @@ class BookshelfController extends Controller
     public function store(Request $request)
     {
         $this->checkPermission('bookshelf-create-all');
-        $this->validate($request, [
+        $validated = $this->validate($request, [
             'name'        => ['required', 'string', 'max:255'],
             'description' => ['string', 'max:1000'],
             'image'       => array_merge(['nullable'], $this->getImageValidationRules()),
+            'tags'        => ['array'],
         ]);
 
         $bookIds = explode(',', $request->get('books', ''));
-        $shelf = $this->bookshelfRepo->create($request->all(), $bookIds);
-        $this->bookshelfRepo->updateCoverImage($shelf, $request->file('image', null));
+        $shelf = $this->bookshelfRepo->create($validated, $bookIds);
 
         return redirect($shelf->getUrl());
     }
@@ -160,16 +160,21 @@ class BookshelfController extends Controller
     {
         $shelf = $this->bookshelfRepo->getBySlug($slug);
         $this->checkOwnablePermission('bookshelf-update', $shelf);
-        $this->validate($request, [
+        $validated = $this->validate($request, [
             'name'        => ['required', 'string', 'max:255'],
             'description' => ['string', 'max:1000'],
             'image'       => array_merge(['nullable'], $this->getImageValidationRules()),
+            'tags'        => ['array'],
         ]);
 
+        if ($request->has('image_reset')) {
+            $validated['image'] = null;
+        } elseif (array_key_exists('image', $validated) && is_null($validated['image'])) {
+            unset($validated['image']);
+        }
+
         $bookIds = explode(',', $request->get('books', ''));
-        $shelf = $this->bookshelfRepo->update($shelf, $request->all(), $bookIds);
-        $resetCover = $request->has('image_reset');
-        $this->bookshelfRepo->updateCoverImage($shelf, $request->file('image', null), $resetCover);
+        $shelf = $this->bookshelfRepo->update($shelf, $validated, $bookIds);
 
         return redirect($shelf->getUrl());
     }
index 83b9bb692da6c3173305c538ab79a6a8a836da86..60eb523800fc369edb694db27e0bcdb065825e15 100644 (file)
@@ -7,6 +7,7 @@ use BookStack\Entities\Models\Book;
 use BookStack\Entities\Repos\ChapterRepo;
 use BookStack\Entities\Tools\BookContents;
 use BookStack\Entities\Tools\Cloner;
+use BookStack\Entities\Tools\HierarchyTransformer;
 use BookStack\Entities\Tools\NextPreviousContentLocator;
 use BookStack\Entities\Tools\PermissionsUpdater;
 use BookStack\Exceptions\MoveOperationException;
@@ -272,4 +273,19 @@ class ChapterController extends Controller
 
         return redirect($chapter->getUrl());
     }
+
+    /**
+     * Convert the chapter to a book.
+     */
+    public function convertToBook(HierarchyTransformer $transformer, string $bookSlug, string $chapterSlug)
+    {
+        $chapter = $this->chapterRepo->getBySlug($bookSlug, $chapterSlug);
+        $this->checkOwnablePermission('chapter-update', $chapter);
+        $this->checkOwnablePermission('chapter-delete', $chapter);
+        $this->checkPermission('book-create-all');
+
+        $book = $transformer->transformChapterToBook($chapter);
+
+        return redirect($book->getUrl());
+    }
 }
index 480280c99ef6dc83a169ba1762d5e4fc0edd4d36..fd56d91b3359218b6f1bf0218761132200bb803d 100644 (file)
@@ -33,7 +33,7 @@ class ChapterExportController extends Controller
         $chapter = $this->chapterRepo->getBySlug($bookSlug, $chapterSlug);
         $pdfContent = $this->exportFormatter->chapterToPdf($chapter);
 
-        return $this->downloadResponse($pdfContent, $chapterSlug . '.pdf');
+        return $this->download()->directly($pdfContent, $chapterSlug . '.pdf');
     }
 
     /**
@@ -47,7 +47,7 @@ class ChapterExportController extends Controller
         $chapter = $this->chapterRepo->getBySlug($bookSlug, $chapterSlug);
         $containedHtml = $this->exportFormatter->chapterToContainedHtml($chapter);
 
-        return $this->downloadResponse($containedHtml, $chapterSlug . '.html');
+        return $this->download()->directly($containedHtml, $chapterSlug . '.html');
     }
 
     /**
@@ -60,7 +60,7 @@ class ChapterExportController extends Controller
         $chapter = $this->chapterRepo->getBySlug($bookSlug, $chapterSlug);
         $chapterText = $this->exportFormatter->chapterToPlainText($chapter);
 
-        return $this->downloadResponse($chapterText, $chapterSlug . '.txt');
+        return $this->download()->directly($chapterText, $chapterSlug . '.txt');
     }
 
     /**
@@ -70,10 +70,9 @@ class ChapterExportController extends Controller
      */
     public function markdown(string $bookSlug, string $chapterSlug)
     {
-        // TODO: This should probably export to a zip file.
         $chapter = $this->chapterRepo->getBySlug($bookSlug, $chapterSlug);
         $chapterText = $this->exportFormatter->chapterToMarkdown($chapter);
 
-        return $this->downloadResponse($chapterText, $chapterSlug . '.md');
+        return $this->download()->directly($chapterText, $chapterSlug . '.md');
     }
 }
index 5b2221fc1235c412ae00c57971d77425ec8b737c..f6dc1dbca43cb9b46ce60ef9d48105f16a04c575 100644 (file)
@@ -4,15 +4,13 @@ namespace BookStack\Http\Controllers;
 
 use BookStack\Exceptions\NotifyException;
 use BookStack\Facades\Activity;
+use BookStack\Http\Responses\DownloadResponseFactory;
 use BookStack\Interfaces\Loggable;
 use BookStack\Model;
-use BookStack\Util\WebSafeMimeSniffer;
 use Illuminate\Foundation\Bus\DispatchesJobs;
 use Illuminate\Foundation\Validation\ValidatesRequests;
 use Illuminate\Http\JsonResponse;
-use Illuminate\Http\Response;
 use Illuminate\Routing\Controller as BaseController;
-use Symfony\Component\HttpFoundation\StreamedResponse;
 
 abstract class Controller extends BaseController
 {
@@ -110,74 +108,11 @@ abstract class Controller extends BaseController
     }
 
     /**
-     * Create a response that forces a download in the browser.
+     * Create and return a new download response factory using the current request.
      */
-    protected function downloadResponse(string $content, string $fileName): Response
+    protected function download(): DownloadResponseFactory
     {
-        return response()->make($content, 200, [
-            'Content-Type'           => 'application/octet-stream',
-            'Content-Disposition'    => 'attachment; filename="' . str_replace('"', '', $fileName) . '"',
-            'X-Content-Type-Options' => 'nosniff',
-        ]);
-    }
-
-    /**
-     * Create a response that forces a download, from a given stream of content.
-     */
-    protected function streamedDownloadResponse($stream, string $fileName): StreamedResponse
-    {
-        return response()->stream(function () use ($stream) {
-
-            // End & flush the output buffer, if we're in one, otherwise we still use memory.
-            // Output buffer may or may not exist depending on PHP `output_buffering` setting.
-            // Ignore in testing since output buffers are used to gather a response.
-            if (!empty(ob_get_status()) && !app()->runningUnitTests()) {
-                ob_end_clean();
-            }
-
-            fpassthru($stream);
-            fclose($stream);
-        }, 200, [
-            'Content-Type'           => 'application/octet-stream',
-            'Content-Disposition'    => 'attachment; filename="' . str_replace('"', '', $fileName) . '"',
-            'X-Content-Type-Options' => 'nosniff',
-        ]);
-    }
-
-    /**
-     * Create a file download response that provides the file with a content-type
-     * correct for the file, in a way so the browser can show the content in browser.
-     */
-    protected function inlineDownloadResponse(string $content, string $fileName): Response
-    {
-        $mime = (new WebSafeMimeSniffer())->sniff($content);
-
-        return response()->make($content, 200, [
-            'Content-Type'           => $mime,
-            'Content-Disposition'    => 'inline; filename="' . str_replace('"', '', $fileName) . '"',
-            'X-Content-Type-Options' => 'nosniff',
-        ]);
-    }
-
-    /**
-     * Create a file download response that provides the file with a content-type
-     * correct for the file, in a way so the browser can show the content in browser,
-     * for a given content stream.
-     */
-    protected function streamedInlineDownloadResponse($stream, string $fileName): StreamedResponse
-    {
-        $sniffContent = fread($stream, 1000);
-        $mime = (new WebSafeMimeSniffer())->sniff($sniffContent);
-
-        return response()->stream(function () use ($sniffContent, $stream) {
-            echo $sniffContent;
-            fpassthru($stream);
-            fclose($stream);
-        }, 200, [
-            'Content-Type'           => $mime,
-            'Content-Disposition'    => 'inline; filename="' . str_replace('"', '', $fileName) . '"',
-            'X-Content-Type-Options' => 'nosniff',
-        ]);
+        return new DownloadResponseFactory(request());
     }
 
     /**
index 0287916de28f40008eeb2d16e948d6274eb77a3a..62101d3390fccca880259f76d824cde7deb2396c 100644 (file)
@@ -36,7 +36,7 @@ class PageExportController extends Controller
         $page->html = (new PageContent($page))->render();
         $pdfContent = $this->exportFormatter->pageToPdf($page);
 
-        return $this->downloadResponse($pdfContent, $pageSlug . '.pdf');
+        return $this->download()->directly($pdfContent, $pageSlug . '.pdf');
     }
 
     /**
@@ -51,7 +51,7 @@ class PageExportController extends Controller
         $page->html = (new PageContent($page))->render();
         $containedHtml = $this->exportFormatter->pageToContainedHtml($page);
 
-        return $this->downloadResponse($containedHtml, $pageSlug . '.html');
+        return $this->download()->directly($containedHtml, $pageSlug . '.html');
     }
 
     /**
@@ -64,7 +64,7 @@ class PageExportController extends Controller
         $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
         $pageText = $this->exportFormatter->pageToPlainText($page);
 
-        return $this->downloadResponse($pageText, $pageSlug . '.txt');
+        return $this->download()->directly($pageText, $pageSlug . '.txt');
     }
 
     /**
@@ -77,6 +77,6 @@ class PageExportController extends Controller
         $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
         $pageText = $this->exportFormatter->pageToMarkdown($page);
 
-        return $this->downloadResponse($pageText, $pageSlug . '.md');
+        return $this->download()->directly($pageText, $pageSlug . '.md');
     }
 }
diff --git a/app/Http/Responses/DownloadResponseFactory.php b/app/Http/Responses/DownloadResponseFactory.php
new file mode 100644 (file)
index 0000000..ec742fc
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+
+namespace BookStack\Http\Responses;
+
+use BookStack\Util\WebSafeMimeSniffer;
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+
+class DownloadResponseFactory
+{
+    protected Request $request;
+
+    public function __construct(Request $request)
+    {
+        $this->request = $request;
+    }
+
+    /**
+     * Create a response that directly forces a download in the browser.
+     */
+    public function directly(string $content, string $fileName): Response
+    {
+        return response()->make($content, 200, $this->getHeaders($fileName));
+    }
+
+    /**
+     * Create a response that forces a download, from a given stream of content.
+     */
+    public function streamedDirectly($stream, string $fileName): StreamedResponse
+    {
+        return response()->stream(function () use ($stream) {
+
+            // End & flush the output buffer, if we're in one, otherwise we still use memory.
+            // Output buffer may or may not exist depending on PHP `output_buffering` setting.
+            // Ignore in testing since output buffers are used to gather a response.
+            if (!empty(ob_get_status()) && !app()->runningUnitTests()) {
+                ob_end_clean();
+            }
+
+            fpassthru($stream);
+            fclose($stream);
+        }, 200, $this->getHeaders($fileName));
+    }
+
+    /**
+     * Create a file download response that provides the file with a content-type
+     * correct for the file, in a way so the browser can show the content in browser,
+     * for a given content stream.
+     */
+    public function streamedInline($stream, string $fileName): StreamedResponse
+    {
+        $sniffContent = fread($stream, 2000);
+        $mime = (new WebSafeMimeSniffer())->sniff($sniffContent);
+
+        return response()->stream(function () use ($sniffContent, $stream) {
+            echo $sniffContent;
+            fpassthru($stream);
+            fclose($stream);
+        }, 200, $this->getHeaders($fileName, $mime));
+    }
+
+    /**
+     * Get the common headers to provide for a download response.
+     */
+    protected function getHeaders(string $fileName, string $mime = 'application/octet-stream'): array
+    {
+        $disposition = ($mime === 'application/octet-stream') ? 'attachment' : 'inline';
+        $downloadName = str_replace('"', '', $fileName);
+
+        return [
+            'Content-Type'           => $mime,
+            'Content-Disposition'    => "{$disposition}; filename=\"{$downloadName}\"",
+            'X-Content-Type-Options' => 'nosniff',
+        ];
+    }
+}
index 9d1f96ae42f99178f6b3fd10406a4572805b5943..6a92cb5a543c6a24b6ae069679965b09cb5dbfbc 100644 (file)
@@ -63,16 +63,6 @@ class AttachmentService
         return 'uploads/files/' . $path;
     }
 
-    /**
-     * Get an attachment from storage.
-     *
-     * @throws FileNotFoundException
-     */
-    public function getAttachmentFromStorage(Attachment $attachment): string
-    {
-        return $this->getStorageDisk()->get($this->adjustPathForStorageDisk($attachment->path));
-    }
-
     /**
      * Stream an attachment from storage.
      *
index ea58e586bbbeab595f804f8a0e40ce3a5ec37cf6..b182d8ac19b39ef6eec4e09acdbe00d8d86c4854 100644 (file)
@@ -17,6 +17,14 @@ class WebSafeMimeSniffer
         'application/json',
         'application/octet-stream',
         'application/pdf',
+        'audio/aac',
+        'audio/midi',
+        'audio/mpeg',
+        'audio/ogg',
+        'audio/opus',
+        'audio/wav',
+        'audio/webm',
+        'audio/x-m4a',
         'image/apng',
         'image/bmp',
         'image/jpeg',
index ebe39a32a9e918f38a8acb5db0c35fc918fd15ba..7135fe6e98326ef88d275439446e3a26f38be38b 100644 (file)
         },
         {
             "name": "aws/aws-sdk-php",
-            "version": "3.222.7",
+            "version": "3.228.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/aws/aws-sdk-php.git",
-                "reference": "03d35eef5c509798d2c08587cfd9a7c33afe2260"
+                "reference": "4ff51d01da43aa3bd36eef921a9cd4e0ff843fab"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/03d35eef5c509798d2c08587cfd9a7c33afe2260",
-                "reference": "03d35eef5c509798d2c08587cfd9a7c33afe2260",
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/4ff51d01da43aa3bd36eef921a9cd4e0ff843fab",
+                "reference": "4ff51d01da43aa3bd36eef921a9cd4e0ff843fab",
                 "shasum": ""
             },
             "require": {
@@ -75,9 +75,9 @@
                 "ext-json": "*",
                 "ext-pcre": "*",
                 "ext-simplexml": "*",
-                "guzzlehttp/guzzle": "^5.3.3 || ^6.2.1 || ^7.0",
+                "guzzlehttp/guzzle": "^6.5.7 || ^7.4.4",
                 "guzzlehttp/promises": "^1.4.0",
-                "guzzlehttp/psr7": "^1.7.0 || ^2.1.1",
+                "guzzlehttp/psr7": "^1.8.5 || ^2.3",
                 "mtdowling/jmespath.php": "^2.6",
                 "php": ">=5.5"
             },
             "support": {
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.222.7"
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.228.0"
             },
-            "time": "2022-05-06T18:16:59+00:00"
+            "time": "2022-06-21T18:13:25+00:00"
         },
         {
             "name": "bacon/bacon-qr-code",
         },
         {
             "name": "barryvdh/laravel-dompdf",
-            "version": "v1.0.0",
+            "version": "v1.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/barryvdh/laravel-dompdf.git",
-                "reference": "e3f429e97087b2ef19b83e5ed313f080f2477685"
+                "reference": "de83130d029289e1b59f28b41c314ce1d157b4a0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/e3f429e97087b2ef19b83e5ed313f080f2477685",
-                "reference": "e3f429e97087b2ef19b83e5ed313f080f2477685",
+                "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/de83130d029289e1b59f28b41c314ce1d157b4a0",
+                "reference": "de83130d029289e1b59f28b41c314ce1d157b4a0",
                 "shasum": ""
             },
             "require": {
-                "dompdf/dompdf": "^1",
+                "dompdf/dompdf": "^1.2.1",
                 "illuminate/support": "^6|^7|^8|^9",
                 "php": "^7.2 || ^8.0"
             },
             ],
             "support": {
                 "issues": "https://github.com/barryvdh/laravel-dompdf/issues",
-                "source": "https://github.com/barryvdh/laravel-dompdf/tree/v1.0.0"
+                "source": "https://github.com/barryvdh/laravel-dompdf/tree/v1.0.2"
             },
             "funding": [
                 {
                     "type": "github"
                 }
             ],
-            "time": "2022-01-29T08:02:59+00:00"
+            "time": "2022-05-19T15:08:38+00:00"
         },
         {
             "name": "barryvdh/laravel-snappy",
         },
         {
             "name": "doctrine/cache",
-            "version": "2.1.1",
+            "version": "2.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/cache.git",
-                "reference": "331b4d5dbaeab3827976273e9356b3b453c300ce"
+                "reference": "1ca8f21980e770095a31456042471a57bc4c68fb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/cache/zipball/331b4d5dbaeab3827976273e9356b3b453c300ce",
-                "reference": "331b4d5dbaeab3827976273e9356b3b453c300ce",
+                "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb",
+                "reference": "1ca8f21980e770095a31456042471a57bc4c68fb",
                 "shasum": ""
             },
             "require": {
                 "doctrine/common": ">2.2,<2.4"
             },
             "require-dev": {
-                "alcaeus/mongo-php-adapter": "^1.1",
                 "cache/integration-tests": "dev-master",
-                "doctrine/coding-standard": "^8.0",
-                "mongodb/mongodb": "^1.1",
-                "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
-                "predis/predis": "~1.0",
+                "doctrine/coding-standard": "^9",
+                "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
                 "psr/cache": "^1.0 || ^2.0 || ^3.0",
-                "symfony/cache": "^4.4 || ^5.2 || ^6.0@dev",
-                "symfony/var-exporter": "^4.4 || ^5.2 || ^6.0@dev"
-            },
-            "suggest": {
-                "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver"
+                "symfony/cache": "^4.4 || ^5.4 || ^6",
+                "symfony/var-exporter": "^4.4 || ^5.4 || ^6"
             },
             "type": "library",
             "autoload": {
             ],
             "support": {
                 "issues": "https://github.com/doctrine/cache/issues",
-                "source": "https://github.com/doctrine/cache/tree/2.1.1"
+                "source": "https://github.com/doctrine/cache/tree/2.2.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-07-17T14:49:29+00:00"
+            "time": "2022-05-20T20:07:39+00:00"
         },
         {
             "name": "doctrine/dbal",
-            "version": "3.3.6",
+            "version": "3.3.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/dbal.git",
-                "reference": "9e7f76dd1cde81c62574fdffa5a9c655c847ad21"
+                "reference": "9f79d4650430b582f4598fe0954ef4d52fbc0a8a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/dbal/zipball/9e7f76dd1cde81c62574fdffa5a9c655c847ad21",
-                "reference": "9e7f76dd1cde81c62574fdffa5a9c655c847ad21",
+                "url": "https://api.github.com/repos/doctrine/dbal/zipball/9f79d4650430b582f4598fe0954ef4d52fbc0a8a",
+                "reference": "9f79d4650430b582f4598fe0954ef4d52fbc0a8a",
                 "shasum": ""
             },
             "require": {
             "require-dev": {
                 "doctrine/coding-standard": "9.0.0",
                 "jetbrains/phpstorm-stubs": "2022.1",
-                "phpstan/phpstan": "1.6.3",
+                "phpstan/phpstan": "1.7.13",
                 "phpstan/phpstan-strict-rules": "^1.2",
                 "phpunit/phpunit": "9.5.20",
                 "psalm/plugin-phpunit": "0.16.1",
-                "squizlabs/php_codesniffer": "3.6.2",
+                "squizlabs/php_codesniffer": "3.7.0",
                 "symfony/cache": "^5.2|^6.0",
                 "symfony/console": "^2.7|^3.0|^4.0|^5.0|^6.0",
                 "vimeo/psalm": "4.23.0"
             ],
             "support": {
                 "issues": "https://github.com/doctrine/dbal/issues",
-                "source": "https://github.com/doctrine/dbal/tree/3.3.6"
+                "source": "https://github.com/doctrine/dbal/tree/3.3.7"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-05-02T17:21:01+00:00"
+            "time": "2022-06-13T21:43:03+00:00"
         },
         {
             "name": "doctrine/deprecations",
         },
         {
             "name": "guzzlehttp/guzzle",
-            "version": "7.4.2",
+            "version": "7.4.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/guzzle.git",
-                "reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4"
+                "reference": "1dd98b0564cb3f6bd16ce683cb755f94c10fbd82"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ac1ec1cd9b5624694c3a40be801d94137afb12b4",
-                "reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4",
+                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1dd98b0564cb3f6bd16ce683cb755f94c10fbd82",
+                "reference": "1dd98b0564cb3f6bd16ce683cb755f94c10fbd82",
                 "shasum": ""
             },
             "require": {
                 "ext-json": "*",
                 "guzzlehttp/promises": "^1.5",
-                "guzzlehttp/psr7": "^1.8.3 || ^2.1",
+                "guzzlehttp/psr7": "^1.9 || ^2.4",
                 "php": "^7.2.5 || ^8.0",
                 "psr/http-client": "^1.0",
                 "symfony/deprecation-contracts": "^2.2 || ^3.0"
             ],
             "support": {
                 "issues": "https://github.com/guzzle/guzzle/issues",
-                "source": "https://github.com/guzzle/guzzle/tree/7.4.2"
+                "source": "https://github.com/guzzle/guzzle/tree/7.4.5"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-03-20T14:16:28+00:00"
+            "time": "2022-06-20T22:16:13+00:00"
         },
         {
             "name": "guzzlehttp/promises",
         },
         {
             "name": "guzzlehttp/psr7",
-            "version": "2.2.1",
+            "version": "2.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/psr7.git",
-                "reference": "c94a94f120803a18554c1805ef2e539f8285f9a2"
+                "reference": "13388f00956b1503577598873fffb5ae994b5737"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/psr7/zipball/c94a94f120803a18554c1805ef2e539f8285f9a2",
-                "reference": "c94a94f120803a18554c1805ef2e539f8285f9a2",
+                "url": "https://api.github.com/repos/guzzle/psr7/zipball/13388f00956b1503577598873fffb5ae994b5737",
+                "reference": "13388f00956b1503577598873fffb5ae994b5737",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.2-dev"
+                    "dev-master": "2.4-dev"
                 }
             },
             "autoload": {
             ],
             "support": {
                 "issues": "https://github.com/guzzle/psr7/issues",
-                "source": "https://github.com/guzzle/psr7/tree/2.2.1"
+                "source": "https://github.com/guzzle/psr7/tree/2.4.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-03-20T21:55:58+00:00"
+            "time": "2022-06-20T21:43:11+00:00"
         },
         {
             "name": "intervention/image",
-            "version": "2.7.1",
+            "version": "2.7.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/Intervention/image.git",
-                "reference": "744ebba495319501b873a4e48787759c72e3fb8c"
+                "reference": "04be355f8d6734c826045d02a1079ad658322dad"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Intervention/image/zipball/744ebba495319501b873a4e48787759c72e3fb8c",
-                "reference": "744ebba495319501b873a4e48787759c72e3fb8c",
+                "url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad",
+                "reference": "04be355f8d6734c826045d02a1079ad658322dad",
                 "shasum": ""
             },
             "require": {
             "authors": [
                 {
                     "name": "Oliver Vogel",
-                    "email": "oliver@olivervogel.com",
-                    "homepage": "http://olivervogel.com/"
+                    "email": "oliver@intervention.io",
+                    "homepage": "https://intervention.io/"
                 }
             ],
             "description": "Image handling and manipulation library with support for Laravel integration",
             ],
             "support": {
                 "issues": "https://github.com/Intervention/image/issues",
-                "source": "https://github.com/Intervention/image/tree/2.7.1"
+                "source": "https://github.com/Intervention/image/tree/2.7.2"
             },
             "funding": [
                 {
-                    "url": "https://www.paypal.me/interventionphp",
+                    "url": "https://paypal.me/interventionio",
                     "type": "custom"
                 },
                 {
                     "type": "github"
                 }
             ],
-            "time": "2021-12-16T16:49:26+00:00"
+            "time": "2022-05-21T17:30:32+00:00"
         },
         {
             "name": "knplabs/knp-snappy",
         },
         {
             "name": "laravel/framework",
-            "version": "v8.83.11",
+            "version": "v8.83.17",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/framework.git",
-                "reference": "d85c34179f209977043502441f9e44ca432a14b4"
+                "reference": "2cf142cd5100b02da248acad3988bdaba5635e16"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/framework/zipball/d85c34179f209977043502441f9e44ca432a14b4",
-                "reference": "d85c34179f209977043502441f9e44ca432a14b4",
+                "url": "https://api.github.com/repos/laravel/framework/zipball/2cf142cd5100b02da248acad3988bdaba5635e16",
+                "reference": "2cf142cd5100b02da248acad3988bdaba5635e16",
                 "shasum": ""
             },
             "require": {
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2022-05-03T14:47:00+00:00"
+            "time": "2022-06-21T14:38:31+00:00"
         },
         {
             "name": "laravel/serializable-closure",
-            "version": "v1.1.1",
+            "version": "v1.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/serializable-closure.git",
-                "reference": "9e4b005daa20b0c161f3845040046dc9ddc1d74e"
+                "reference": "09f0e9fb61829f628205b7c94906c28740ff9540"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/9e4b005daa20b0c161f3845040046dc9ddc1d74e",
-                "reference": "9e4b005daa20b0c161f3845040046dc9ddc1d74e",
+                "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/09f0e9fb61829f628205b7c94906c28740ff9540",
+                "reference": "09f0e9fb61829f628205b7c94906c28740ff9540",
                 "shasum": ""
             },
             "require": {
                 "issues": "https://github.com/laravel/serializable-closure/issues",
                 "source": "https://github.com/laravel/serializable-closure"
             },
-            "time": "2022-02-11T19:23:53+00:00"
+            "time": "2022-05-16T17:09:47+00:00"
         },
         {
             "name": "laravel/socialite",
         },
         {
             "name": "laravel/ui",
-            "version": "v3.4.5",
+            "version": "v3.4.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/ui.git",
-                "reference": "f11d295de1508c5bb56206a620b00b6616de414c"
+                "reference": "65ec5c03f7fee2c8ecae785795b829a15be48c2c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/ui/zipball/f11d295de1508c5bb56206a620b00b6616de414c",
-                "reference": "f11d295de1508c5bb56206a620b00b6616de414c",
+                "url": "https://api.github.com/repos/laravel/ui/zipball/65ec5c03f7fee2c8ecae785795b829a15be48c2c",
+                "reference": "65ec5c03f7fee2c8ecae785795b829a15be48c2c",
                 "shasum": ""
             },
             "require": {
                 "ui"
             ],
             "support": {
-                "source": "https://github.com/laravel/ui/tree/v3.4.5"
+                "source": "https://github.com/laravel/ui/tree/v3.4.6"
             },
-            "time": "2022-02-21T14:59:16+00:00"
+            "time": "2022-05-20T13:38:08+00:00"
         },
         {
             "name": "league/commonmark",
         },
         {
             "name": "monolog/monolog",
-            "version": "2.5.0",
+            "version": "2.7.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/Seldaek/monolog.git",
-                "reference": "4192345e260f1d51b365536199744b987e160edc"
+                "reference": "5579edf28aee1190a798bfa5be8bc16c563bd524"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4192345e260f1d51b365536199744b987e160edc",
-                "reference": "4192345e260f1d51b365536199744b987e160edc",
+                "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5579edf28aee1190a798bfa5be8bc16c563bd524",
+                "reference": "5579edf28aee1190a798bfa5be8bc16c563bd524",
                 "shasum": ""
             },
             "require": {
             "require-dev": {
                 "aws/aws-sdk-php": "^2.4.9 || ^3.0",
                 "doctrine/couchdb": "~1.0@dev",
-                "elasticsearch/elasticsearch": "^7",
+                "elasticsearch/elasticsearch": "^7 || ^8",
+                "ext-json": "*",
                 "graylog2/gelf-php": "^1.4.2",
+                "guzzlehttp/guzzle": "^7.4",
+                "guzzlehttp/psr7": "^2.2",
                 "mongodb/mongodb": "^1.8",
                 "php-amqplib/php-amqplib": "~2.4 || ^3",
                 "php-console/php-console": "^3.1.3",
-                "phpspec/prophecy": "^1.6.1",
+                "phpspec/prophecy": "^1.15",
                 "phpstan/phpstan": "^0.12.91",
-                "phpunit/phpunit": "^8.5",
+                "phpunit/phpunit": "^8.5.14",
                 "predis/predis": "^1.1",
                 "rollbar/rollbar": "^1.3 || ^2 || ^3",
-                "ruflin/elastica": ">=0.90@dev",
-                "swiftmailer/swiftmailer": "^5.3|^6.0"
+                "ruflin/elastica": "^7",
+                "swiftmailer/swiftmailer": "^5.3|^6.0",
+                "symfony/mailer": "^5.4 || ^6",
+                "symfony/mime": "^5.4 || ^6"
             },
             "suggest": {
                 "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
             ],
             "support": {
                 "issues": "https://github.com/Seldaek/monolog/issues",
-                "source": "https://github.com/Seldaek/monolog/tree/2.5.0"
+                "source": "https://github.com/Seldaek/monolog/tree/2.7.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-04-08T15:43:54+00:00"
+            "time": "2022-06-09T08:59:12+00:00"
         },
         {
             "name": "mtdowling/jmespath.php",
         },
         {
             "name": "nikic/php-parser",
-            "version": "v4.13.2",
+            "version": "v4.14.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nikic/PHP-Parser.git",
-                "reference": "210577fe3cf7badcc5814d99455df46564f3c077"
+                "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077",
-                "reference": "210577fe3cf7badcc5814d99455df46564f3c077",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1",
+                "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1",
                 "shasum": ""
             },
             "require": {
             ],
             "support": {
                 "issues": "https://github.com/nikic/PHP-Parser/issues",
-                "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2"
+                "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0"
             },
-            "time": "2021-11-30T19:35:32+00:00"
+            "time": "2022-05-31T20:59:12+00:00"
         },
         {
             "name": "onelogin/php-saml",
-            "version": "4.0.0",
+            "version": "4.0.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/onelogin/php-saml.git",
-                "reference": "f30f5062f3653c4d2082892d207f4dc3e577d979"
+                "reference": "247a45c079e65a78185d5489bdda0f95826c014d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/onelogin/php-saml/zipball/f30f5062f3653c4d2082892d207f4dc3e577d979",
-                "reference": "f30f5062f3653c4d2082892d207f4dc3e577d979",
+                "url": "https://api.github.com/repos/onelogin/php-saml/zipball/247a45c079e65a78185d5489bdda0f95826c014d",
+                "reference": "247a45c079e65a78185d5489bdda0f95826c014d",
                 "shasum": ""
             },
             "require": {
                 "issues": "https://github.com/onelogin/php-saml/issues",
                 "source": "https://github.com/onelogin/php-saml/"
             },
-            "time": "2021-03-02T10:19:19+00:00"
+            "time": "2022-06-15T16:07:51+00:00"
         },
         {
             "name": "opis/closure",
         },
         {
             "name": "paragonie/constant_time_encoding",
-            "version": "v2.5.0",
+            "version": "v2.6.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/paragonie/constant_time_encoding.git",
-                "reference": "9229e15f2e6ba772f0c55dd6986c563b937170a8"
+                "reference": "58c3f47f650c94ec05a151692652a868995d2938"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/9229e15f2e6ba772f0c55dd6986c563b937170a8",
-                "reference": "9229e15f2e6ba772f0c55dd6986c563b937170a8",
+                "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/58c3f47f650c94ec05a151692652a868995d2938",
+                "reference": "58c3f47f650c94ec05a151692652a868995d2938",
                 "shasum": ""
             },
             "require": {
                 "issues": "https://github.com/paragonie/constant_time_encoding/issues",
                 "source": "https://github.com/paragonie/constant_time_encoding"
             },
-            "time": "2022-01-17T05:32:27+00:00"
+            "time": "2022-06-14T06:56:20+00:00"
         },
         {
             "name": "paragonie/random_compat",
         },
         {
             "name": "pragmarx/google2fa",
-            "version": "8.0.0",
+            "version": "v8.0.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/antonioribeiro/google2fa.git",
-                "reference": "26c4c5cf30a2844ba121760fd7301f8ad240100b"
+                "reference": "80c3d801b31fe165f8fe99ea085e0a37834e1be3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/26c4c5cf30a2844ba121760fd7301f8ad240100b",
-                "reference": "26c4c5cf30a2844ba121760fd7301f8ad240100b",
+                "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/80c3d801b31fe165f8fe99ea085e0a37834e1be3",
+                "reference": "80c3d801b31fe165f8fe99ea085e0a37834e1be3",
                 "shasum": ""
             },
             "require": {
             ],
             "support": {
                 "issues": "https://github.com/antonioribeiro/google2fa/issues",
-                "source": "https://github.com/antonioribeiro/google2fa/tree/8.0.0"
+                "source": "https://github.com/antonioribeiro/google2fa/tree/v8.0.1"
             },
-            "time": "2020-04-05T10:47:18+00:00"
+            "time": "2022-06-13T21:57:56+00:00"
         },
         {
             "name": "predis/predis",
         },
         {
             "name": "psy/psysh",
-            "version": "v0.11.4",
+            "version": "v0.11.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/bobthecow/psysh.git",
-                "reference": "05c544b339b112226ad14803e1e5b09a61957454"
+                "reference": "c23686f9c48ca202710dbb967df8385a952a2daf"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/bobthecow/psysh/zipball/05c544b339b112226ad14803e1e5b09a61957454",
-                "reference": "05c544b339b112226ad14803e1e5b09a61957454",
+                "url": "https://api.github.com/repos/bobthecow/psysh/zipball/c23686f9c48ca202710dbb967df8385a952a2daf",
+                "reference": "c23686f9c48ca202710dbb967df8385a952a2daf",
                 "shasum": ""
             },
             "require": {
             ],
             "support": {
                 "issues": "https://github.com/bobthecow/psysh/issues",
-                "source": "https://github.com/bobthecow/psysh/tree/v0.11.4"
+                "source": "https://github.com/bobthecow/psysh/tree/v0.11.5"
             },
-            "time": "2022-05-06T12:49:14+00:00"
+            "time": "2022-05-27T18:03:49+00:00"
         },
         {
             "name": "ralouphie/getallheaders",
         },
         {
             "name": "symfony/console",
-            "version": "v5.4.8",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "ffe3aed36c4d60da2cf1b0a1cee6b8f2e5fa881b"
+                "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/ffe3aed36c4d60da2cf1b0a1cee6b8f2e5fa881b",
-                "reference": "ffe3aed36c4d60da2cf1b0a1cee6b8f2e5fa881b",
+                "url": "https://api.github.com/repos/symfony/console/zipball/829d5d1bf60b2efeb0887b7436873becc71a45eb",
+                "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb",
                 "shasum": ""
             },
             "require": {
                 "terminal"
             ],
             "support": {
-                "source": "https://github.com/symfony/console/tree/v5.4.8"
+                "source": "https://github.com/symfony/console/tree/v5.4.9"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-04-12T16:02:29+00:00"
+            "time": "2022-05-18T06:17:34+00:00"
         },
         {
             "name": "symfony/css-selector",
         },
         {
             "name": "symfony/error-handler",
-            "version": "v5.4.8",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/error-handler.git",
-                "reference": "c1fcde614dfe99d62a83b796a53b8bad358b266a"
+                "reference": "c116cda1f51c678782768dce89a45f13c949455d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/error-handler/zipball/c1fcde614dfe99d62a83b796a53b8bad358b266a",
-                "reference": "c1fcde614dfe99d62a83b796a53b8bad358b266a",
+                "url": "https://api.github.com/repos/symfony/error-handler/zipball/c116cda1f51c678782768dce89a45f13c949455d",
+                "reference": "c116cda1f51c678782768dce89a45f13c949455d",
                 "shasum": ""
             },
             "require": {
             "description": "Provides tools to manage errors and ease debugging PHP code",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/error-handler/tree/v5.4.8"
+                "source": "https://github.com/symfony/error-handler/tree/v5.4.9"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-04-12T15:48:08+00:00"
+            "time": "2022-05-21T13:57:48+00:00"
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v5.4.3",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git",
-                "reference": "dec8a9f58d20df252b9cd89f1c6c1530f747685d"
+                "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dec8a9f58d20df252b9cd89f1c6c1530f747685d",
-                "reference": "dec8a9f58d20df252b9cd89f1c6c1530f747685d",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc",
+                "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc",
                 "shasum": ""
             },
             "require": {
             "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.3"
+                "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.9"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-01-02T09:53:40+00:00"
+            "time": "2022-05-05T16:45:39+00:00"
         },
         {
             "name": "symfony/event-dispatcher-contracts",
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v5.4.8",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-foundation.git",
-                "reference": "ff2818d1c3d49860bcae1f2cbb5eb00fcd3bf9e2"
+                "reference": "6b0d0e4aca38d57605dcd11e2416994b38774522"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ff2818d1c3d49860bcae1f2cbb5eb00fcd3bf9e2",
-                "reference": "ff2818d1c3d49860bcae1f2cbb5eb00fcd3bf9e2",
+                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6b0d0e4aca38d57605dcd11e2416994b38774522",
+                "reference": "6b0d0e4aca38d57605dcd11e2416994b38774522",
                 "shasum": ""
             },
             "require": {
             "description": "Defines an object-oriented layer for the HTTP specification",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/http-foundation/tree/v5.4.8"
+                "source": "https://github.com/symfony/http-foundation/tree/v5.4.9"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-04-22T08:14:12+00:00"
+            "time": "2022-05-17T15:07:29+00:00"
         },
         {
             "name": "symfony/http-kernel",
-            "version": "v5.4.8",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-kernel.git",
-                "reference": "cf7e61106abfc19b305ca0aedc41724ced89a02a"
+                "reference": "34b121ad3dc761f35fe1346d2f15618f8cbf77f8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/cf7e61106abfc19b305ca0aedc41724ced89a02a",
-                "reference": "cf7e61106abfc19b305ca0aedc41724ced89a02a",
+                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/34b121ad3dc761f35fe1346d2f15618f8cbf77f8",
+                "reference": "34b121ad3dc761f35fe1346d2f15618f8cbf77f8",
                 "shasum": ""
             },
             "require": {
             "description": "Provides a structured process for converting a Request into a Response",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/http-kernel/tree/v5.4.8"
+                "source": "https://github.com/symfony/http-kernel/tree/v5.4.9"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-04-27T17:22:21+00:00"
+            "time": "2022-05-27T07:09:08+00:00"
         },
         {
             "name": "symfony/mime",
-            "version": "v5.4.8",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/mime.git",
-                "reference": "af49bc163ec3272f677bde3bc44c0d766c1fd662"
+                "reference": "2b3802a24e48d0cfccf885173d2aac91e73df92e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/mime/zipball/af49bc163ec3272f677bde3bc44c0d766c1fd662",
-                "reference": "af49bc163ec3272f677bde3bc44c0d766c1fd662",
+                "url": "https://api.github.com/repos/symfony/mime/zipball/2b3802a24e48d0cfccf885173d2aac91e73df92e",
+                "reference": "2b3802a24e48d0cfccf885173d2aac91e73df92e",
                 "shasum": ""
             },
             "require": {
                 "mime-type"
             ],
             "support": {
-                "source": "https://github.com/symfony/mime/tree/v5.4.8"
+                "source": "https://github.com/symfony/mime/tree/v5.4.9"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-04-12T15:48:08+00:00"
+            "time": "2022-05-21T10:24:18+00:00"
         },
         {
             "name": "symfony/polyfill-ctype",
-            "version": "v1.25.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-ctype.git",
-                "reference": "30885182c981ab175d4d034db0f6f469898070ab"
+                "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
-                "reference": "30885182c981ab175d4d034db0f6f469898070ab",
+                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
+                "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
                 "portable"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
+                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-10-20T20:35:02+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-iconv",
-            "version": "v1.25.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-iconv.git",
-                "reference": "f1aed619e28cb077fc83fac8c4c0383578356e40"
+                "reference": "143f1881e655bebca1312722af8068de235ae5dc"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/f1aed619e28cb077fc83fac8c4c0383578356e40",
-                "reference": "f1aed619e28cb077fc83fac8c4c0383578356e40",
+                "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/143f1881e655bebca1312722af8068de235ae5dc",
+                "reference": "143f1881e655bebca1312722af8068de235ae5dc",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-iconv/tree/v1.25.0"
+                "source": "https://github.com/symfony/polyfill-iconv/tree/v1.26.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-01-04T09:04:05+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-intl-grapheme",
-            "version": "v1.25.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
-                "reference": "81b86b50cf841a64252b439e738e97f4a34e2783"
+                "reference": "433d05519ce6990bf3530fba6957499d327395c2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783",
-                "reference": "81b86b50cf841a64252b439e738e97f4a34e2783",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
+                "reference": "433d05519ce6990bf3530fba6957499d327395c2",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
+                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-11-23T21:10:46+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-intl-idn",
-            "version": "v1.25.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-intl-idn.git",
-                "reference": "749045c69efb97c70d25d7463abba812e91f3a44"
+                "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/749045c69efb97c70d25d7463abba812e91f3a44",
-                "reference": "749045c69efb97c70d25d7463abba812e91f3a44",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
+                "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.25.0"
+                "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-09-14T14:02:44+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-intl-normalizer",
-            "version": "v1.25.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
-                "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
+                "reference": "219aa369ceff116e673852dce47c3a41794c14bd"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
-                "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
+                "reference": "219aa369ceff116e673852dce47c3a41794c14bd",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
+                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-02-19T12:13:01+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-mbstring",
-            "version": "v1.25.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-mbstring.git",
-                "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
+                "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
-                "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
+                "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
+                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-11-30T18:21:41+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-php72",
-            "version": "v1.25.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php72.git",
-                "reference": "9a142215a36a3888e30d0a9eeea9766764e96976"
+                "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976",
-                "reference": "9a142215a36a3888e30d0a9eeea9766764e96976",
+                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
+                "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0"
+                "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-05-27T09:17:38+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-php73",
-            "version": "v1.25.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php73.git",
-                "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5"
+                "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5",
-                "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5",
+                "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
+                "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0"
+                "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-06-05T21:20:04+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-php80",
-            "version": "v1.25.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php80.git",
-                "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
+                "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
-                "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
+                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
+                "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
+                "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-03-04T08:16:47+00:00"
+            "time": "2022-05-10T07:21:04+00:00"
         },
         {
             "name": "symfony/polyfill-php81",
-            "version": "v1.25.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php81.git",
-                "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f"
+                "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/5de4ba2d41b15f9bd0e19b2ab9674135813ec98f",
-                "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f",
+                "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1",
+                "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1",
                 "shasum": ""
             },
             "require": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0"
+                "source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-09-13T13:58:11+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/process",
         },
         {
             "name": "symfony/string",
-            "version": "v5.4.8",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/string.git",
-                "reference": "3c061a76bff6d6ea427d85e12ad1bb8ed8cd43e8"
+                "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/string/zipball/3c061a76bff6d6ea427d85e12ad1bb8ed8cd43e8",
-                "reference": "3c061a76bff6d6ea427d85e12ad1bb8ed8cd43e8",
+                "url": "https://api.github.com/repos/symfony/string/zipball/985e6a9703ef5ce32ba617c9c7d97873bb7b2a99",
+                "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99",
                 "shasum": ""
             },
             "require": {
                 "utf8"
             ],
             "support": {
-                "source": "https://github.com/symfony/string/tree/v5.4.8"
+                "source": "https://github.com/symfony/string/tree/v5.4.9"
             },
             "funding": [
                 {
         },
         {
             "name": "symfony/translation",
-            "version": "v5.4.8",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/translation.git",
-                "reference": "f5c0f6d1f20993b2606f3a5f36b1dc8c1899170b"
+                "reference": "1639abc1177d26bcd4320e535e664cef067ab0ca"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/translation/zipball/f5c0f6d1f20993b2606f3a5f36b1dc8c1899170b",
-                "reference": "f5c0f6d1f20993b2606f3a5f36b1dc8c1899170b",
+                "url": "https://api.github.com/repos/symfony/translation/zipball/1639abc1177d26bcd4320e535e664cef067ab0ca",
+                "reference": "1639abc1177d26bcd4320e535e664cef067ab0ca",
                 "shasum": ""
             },
             "require": {
             "description": "Provides tools to internationalize your application",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/translation/tree/v5.4.8"
+                "source": "https://github.com/symfony/translation/tree/v5.4.9"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-04-22T08:14:12+00:00"
+            "time": "2022-05-06T12:33:37+00:00"
         },
         {
             "name": "symfony/translation-contracts",
         },
         {
             "name": "symfony/var-dumper",
-            "version": "v5.4.8",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-dumper.git",
-                "reference": "cdcadd343d31ad16fc5e006b0de81ea307435053"
+                "reference": "af52239a330fafd192c773795520dc2dd62b5657"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/cdcadd343d31ad16fc5e006b0de81ea307435053",
-                "reference": "cdcadd343d31ad16fc5e006b0de81ea307435053",
+                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/af52239a330fafd192c773795520dc2dd62b5657",
+                "reference": "af52239a330fafd192c773795520dc2dd62b5657",
                 "shasum": ""
             },
             "require": {
                 "dump"
             ],
             "support": {
-                "source": "https://github.com/symfony/var-dumper/tree/v5.4.8"
+                "source": "https://github.com/symfony/var-dumper/tree/v5.4.9"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-04-26T13:19:20+00:00"
+            "time": "2022-05-21T10:24:18+00:00"
         },
         {
             "name": "tijsverkoyen/css-to-inline-styles",
         },
         {
             "name": "webmozart/assert",
-            "version": "1.10.0",
+            "version": "1.11.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/webmozarts/assert.git",
-                "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
+                "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
-                "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
+                "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
+                "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.2 || ^8.0",
-                "symfony/polyfill-ctype": "^1.8"
+                "ext-ctype": "*",
+                "php": "^7.2 || ^8.0"
             },
             "conflict": {
                 "phpstan/phpstan": "<0.12.20",
             ],
             "support": {
                 "issues": "https://github.com/webmozarts/assert/issues",
-                "source": "https://github.com/webmozarts/assert/tree/1.10.0"
+                "source": "https://github.com/webmozarts/assert/tree/1.11.0"
             },
-            "time": "2021-03-09T10:59:23+00:00"
+            "time": "2022-06-03T18:03:27+00:00"
         }
     ],
     "packages-dev": [
         {
             "name": "composer/ca-bundle",
-            "version": "1.3.1",
+            "version": "1.3.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/ca-bundle.git",
-                "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b"
+                "reference": "fd5dd441932a7e10ca6e5b490e272d34c8430640"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/ca-bundle/zipball/4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b",
-                "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b",
+                "url": "https://api.github.com/repos/composer/ca-bundle/zipball/fd5dd441932a7e10ca6e5b490e272d34c8430640",
+                "reference": "fd5dd441932a7e10ca6e5b490e272d34c8430640",
                 "shasum": ""
             },
             "require": {
             "support": {
                 "irc": "irc://irc.freenode.org/composer",
                 "issues": "https://github.com/composer/ca-bundle/issues",
-                "source": "https://github.com/composer/ca-bundle/tree/1.3.1"
+                "source": "https://github.com/composer/ca-bundle/tree/1.3.2"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-10-28T20:44:15+00:00"
+            "time": "2022-05-24T11:56:16+00:00"
         },
         {
             "name": "composer/composer",
-            "version": "2.3.5",
+            "version": "2.3.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/composer.git",
-                "reference": "50c47b1f907cfcdb8f072b88164d22b527557ae1"
+                "reference": "10cd375cf85dede2ff417ceab517ef9a0dc55407"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/composer/zipball/50c47b1f907cfcdb8f072b88164d22b527557ae1",
-                "reference": "50c47b1f907cfcdb8f072b88164d22b527557ae1",
+                "url": "https://api.github.com/repos/composer/composer/zipball/10cd375cf85dede2ff417ceab517ef9a0dc55407",
+                "reference": "10cd375cf85dede2ff417ceab517ef9a0dc55407",
                 "shasum": ""
             },
             "require": {
                 "react/promise": "^2.8",
                 "seld/jsonlint": "^1.4",
                 "seld/phar-utils": "^1.2",
-                "symfony/console": "^5.4.1 || ^6.0",
+                "symfony/console": "^5.4.7 || ^6.0.7",
                 "symfony/filesystem": "^5.4 || ^6.0",
                 "symfony/finder": "^5.4 || ^6.0",
                 "symfony/polyfill-php73": "^1.24",
             "extra": {
                 "branch-alias": {
                     "dev-main": "2.3-dev"
+                },
+                "phpstan": {
+                    "includes": [
+                        "phpstan/rules.neon"
+                    ]
                 }
             },
             "autoload": {
             "support": {
                 "irc": "ircs://irc.libera.chat:6697/composer",
                 "issues": "https://github.com/composer/composer/issues",
-                "source": "https://github.com/composer/composer/tree/2.3.5"
+                "source": "https://github.com/composer/composer/tree/2.3.7"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-04-13T14:43:00+00:00"
+            "time": "2022-06-06T14:43:28+00:00"
         },
         {
             "name": "composer/metadata-minifier",
         },
         {
             "name": "composer/spdx-licenses",
-            "version": "1.5.6",
+            "version": "1.5.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/spdx-licenses.git",
-                "reference": "a30d487169d799745ca7280bc90fdfa693536901"
+                "reference": "c848241796da2abf65837d51dce1fae55a960149"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/a30d487169d799745ca7280bc90fdfa693536901",
-                "reference": "a30d487169d799745ca7280bc90fdfa693536901",
+                "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/c848241796da2abf65837d51dce1fae55a960149",
+                "reference": "c848241796da2abf65837d51dce1fae55a960149",
                 "shasum": ""
             },
             "require": {
             "support": {
                 "irc": "irc://irc.freenode.org/composer",
                 "issues": "https://github.com/composer/spdx-licenses/issues",
-                "source": "https://github.com/composer/spdx-licenses/tree/1.5.6"
+                "source": "https://github.com/composer/spdx-licenses/tree/1.5.7"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-11-18T10:14:14+00:00"
+            "time": "2022-05-23T07:37:50+00:00"
         },
         {
             "name": "composer/xdebug-handler",
         },
         {
             "name": "phpstan/phpstan",
-            "version": "1.6.7",
+            "version": "1.7.15",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpstan/phpstan.git",
-                "reference": "d41c39cb2e487663bce9bbd97c660e244b73abad"
+                "reference": "cd0202ea1b1fc6d1bbe156c6e2e18a03e0ff160a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/d41c39cb2e487663bce9bbd97c660e244b73abad",
-                "reference": "d41c39cb2e487663bce9bbd97c660e244b73abad",
+                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd0202ea1b1fc6d1bbe156c6e2e18a03e0ff160a",
+                "reference": "cd0202ea1b1fc6d1bbe156c6e2e18a03e0ff160a",
                 "shasum": ""
             },
             "require": {
             "description": "PHPStan - PHP Static Analysis Tool",
             "support": {
                 "issues": "https://github.com/phpstan/phpstan/issues",
-                "source": "https://github.com/phpstan/phpstan/tree/1.6.7"
+                "source": "https://github.com/phpstan/phpstan/tree/1.7.15"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-05-04T22:55:41+00:00"
+            "time": "2022-06-20T08:29:01+00:00"
         },
         {
             "name": "phpunit/php-code-coverage",
         },
         {
             "name": "phpunit/phpunit",
-            "version": "9.5.20",
+            "version": "9.5.21",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba"
+                "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/12bc8879fb65aef2138b26fc633cb1e3620cffba",
-                "reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e32b76be457de00e83213528f6bb37e2a38fcb1",
+                "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1",
                 "shasum": ""
             },
             "require": {
                 "sebastian/version": "^3.0.2"
             },
             "require-dev": {
-                "ext-pdo": "*",
                 "phpspec/prophecy-phpunit": "^2.0.1"
             },
             "suggest": {
             ],
             "support": {
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.20"
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.21"
             },
             "funding": [
                 {
                     "type": "github"
                 }
             ],
-            "time": "2022-04-01T12:37:26+00:00"
+            "time": "2022-06-19T12:14:25+00:00"
         },
         {
             "name": "react/promise",
         },
         {
             "name": "symfony/dom-crawler",
-            "version": "v5.4.6",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/dom-crawler.git",
-                "reference": "c0bda97480d96337bd3866026159a8b358665457"
+                "reference": "a213cbc80382320b0efdccdcdce232f191fafe3a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/c0bda97480d96337bd3866026159a8b358665457",
-                "reference": "c0bda97480d96337bd3866026159a8b358665457",
+                "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/a213cbc80382320b0efdccdcdce232f191fafe3a",
+                "reference": "a213cbc80382320b0efdccdcdce232f191fafe3a",
                 "shasum": ""
             },
             "require": {
             "description": "Eases DOM navigation for HTML and XML documents",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/dom-crawler/tree/v5.4.6"
+                "source": "https://github.com/symfony/dom-crawler/tree/v5.4.9"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-03-02T12:42:23+00:00"
+            "time": "2022-05-04T14:46:32+00:00"
         },
         {
             "name": "symfony/filesystem",
-            "version": "v5.4.7",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/filesystem.git",
-                "reference": "3a4442138d80c9f7b600fb297534ac718b61d37f"
+                "reference": "36a017fa4cce1eff1b8e8129ff53513abcef05ba"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/filesystem/zipball/3a4442138d80c9f7b600fb297534ac718b61d37f",
-                "reference": "3a4442138d80c9f7b600fb297534ac718b61d37f",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/36a017fa4cce1eff1b8e8129ff53513abcef05ba",
+                "reference": "36a017fa4cce1eff1b8e8129ff53513abcef05ba",
                 "shasum": ""
             },
             "require": {
             "description": "Provides basic utilities for the filesystem",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/filesystem/tree/v5.4.7"
+                "source": "https://github.com/symfony/filesystem/tree/v5.4.9"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-04-01T12:33:59+00:00"
+            "time": "2022-05-20T13:55:35+00:00"
         },
         {
             "name": "theseer/tokenizer",
index a952e0487f1677e2b2876c360eb2970cfe6c9a64..6ab3d710e96f8e61f32288f12dba915f5e26f6a8 100644 (file)
@@ -21,8 +21,9 @@ class RoleFactory extends Factory
     public function definition()
     {
         return [
-            'display_name' => $this->faker->sentence(3),
-            'description'  => $this->faker->sentence(10),
+            'display_name'     => $this->faker->sentence(3),
+            'description'      => $this->faker->sentence(10),
+            'external_auth_id' => '',
         ];
     }
 }
index 45a8c542f387b0a8000387fd2ccb2bcb9e72aa65..0f8458feda29861821108f85b887ec4261b22e7a 100644 (file)
@@ -9,8 +9,7 @@
       "updated_at": "2019-12-11T20:57:31.000000Z",
       "created_by": 1,
       "updated_by": 1,
-      "owned_by": 1,
-      "image_id": 3
+      "owned_by": 1
     },
     {
       "id": 2,
@@ -21,8 +20,7 @@
       "updated_at": "2019-12-11T20:57:23.000000Z",
       "created_by": 4,
       "updated_by": 3,
-      "owned_by": 3,
-      "image_id": 34
+      "owned_by": 3
     }
   ],
   "total": 14
index 30c910aa32db870deed44c4954b894f6df8e142e..7d3d6735e1ecaa9efea5c39c3da88cf16b5e2dd4 100644 (file)
@@ -7,6 +7,5 @@
   "updated_at": "2020-01-12T14:16:10.000000Z",
   "created_by": 1,
   "updated_by": 1,
-  "owned_by": 1,
-  "image_id": 452
+  "owned_by": 1
 }
\ No newline at end of file
index 82ead7d93a3da98279cef96cb1d2a905218fe317..4b1a1b43f930fc27b92694d23ecc0e29c822a86d 100644 (file)
@@ -9,8 +9,7 @@
       "updated_at": "2020-04-10T13:00:45.000000Z",
       "created_by": 4,
       "updated_by": 1,
-      "owned_by": 1,
-      "image_id": 31
+      "owned_by": 1
     },
     {
       "id": 9,
@@ -21,8 +20,7 @@
       "updated_at": "2020-04-10T13:00:58.000000Z",
       "created_by": 4,
       "updated_by": 1,
-      "owned_by": 1,
-      "image_id": 28
+      "owned_by": 1
     },
     {
       "id": 10,
@@ -33,8 +31,7 @@
       "updated_at": "2020-04-10T13:00:53.000000Z",
       "created_by": 4,
       "updated_by": 1,
-      "owned_by": 4,
-      "image_id": 30
+      "owned_by": 4
     }
   ],
   "total": 3
index 551dacb1f305aebcf55b2d3355266676cc8151a9..e199d8d68a552cfc96664ff6aa7ad09f33b20c84 100644 (file)
@@ -6,7 +6,6 @@
   "created_by": 1,
   "updated_by": 1,
   "owned_by": 1,
-  "image_id": 501,
   "created_at": "2020-04-10T13:24:09.000000Z",
   "updated_at": "2020-04-10T13:48:22.000000Z"
 }
\ No newline at end of file
index 7f0df22827f0d874439831c512f6a3c66ba13b0a..1448d592fa0f72b3f40b39fc4b86d033fb402928 100644 (file)
@@ -5,20 +5,21 @@
   "packages": {
     "": {
       "dependencies": {
-        "clipboard": "^2.0.10",
-        "codemirror": "^5.65.2",
+        "clipboard": "^2.0.11",
+        "codemirror": "^5.65.5",
         "dropzone": "^5.9.3",
-        "markdown-it": "^12.3.2",
+        "markdown-it": "^13.0.1",
         "markdown-it-task-lists": "^2.1.1",
+        "snabbdom": "^3.5.0",
         "sortablejs": "^1.15.0"
       },
       "devDependencies": {
         "chokidar-cli": "^3.0",
-        "esbuild": "0.14.36",
+        "esbuild": "0.14.42",
         "livereload": "^0.9.3",
         "npm-run-all": "^4.1.5",
         "punycode": "^2.1.1",
-        "sass": "^1.50.0"
+        "sass": "^1.52.1"
       }
     },
     "node_modules/ansi-regex": {
       }
     },
     "node_modules/clipboard": {
-      "version": "2.0.10",
-      "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.10.tgz",
-      "integrity": "sha512-cz3m2YVwFz95qSEbCDi2fzLN/epEN9zXBvfgAoGkvGOJZATMl9gtTDVOtBYkx2ODUJl2kvmud7n32sV2BpYR4g==",
+      "version": "2.0.11",
+      "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz",
+      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
       "dependencies": {
         "good-listener": "^1.2.2",
         "select": "^1.1.2",
       }
     },
     "node_modules/codemirror": {
-      "version": "5.65.2",
-      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.2.tgz",
-      "integrity": "sha512-SZM4Zq7XEC8Fhroqe3LxbEEX1zUPWH1wMr5zxiBuiUF64iYOUH/JI88v4tBag8MiBS8B8gRv8O1pPXGYXQ4ErA=="
+      "version": "5.65.5",
+      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.5.tgz",
+      "integrity": "sha512-HNyhvGLnYz5c+kIsB9QKVitiZUevha3ovbIYaQiGzKo7ECSL/elWD9RXt3JgNr0NdnyqE9/Rc/7uLfkJQL638w=="
     },
     "node_modules/color-convert": {
       "version": "1.9.3",
       "dev": true
     },
     "node_modules/entities": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
-      "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
+      "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
+      "engines": {
+        "node": ">=0.12"
+      },
       "funding": {
         "url": "https://github.com/fb55/entities?sponsor=1"
       }
       }
     },
     "node_modules/esbuild": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.36.tgz",
-      "integrity": "sha512-HhFHPiRXGYOCRlrhpiVDYKcFJRdO0sBElZ668M4lh2ER0YgnkLxECuFe7uWCf23FrcLc59Pqr7dHkTqmRPDHmw==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.42.tgz",
+      "integrity": "sha512-V0uPZotCEHokJdNqyozH6qsaQXqmZEOiZWrXnds/zaH/0SyrIayRXWRB98CENO73MIZ9T3HBIOsmds5twWtmgw==",
       "dev": true,
       "hasInstallScript": true,
       "bin": {
         "node": ">=12"
       },
       "optionalDependencies": {
-        "esbuild-android-64": "0.14.36",
-        "esbuild-android-arm64": "0.14.36",
-        "esbuild-darwin-64": "0.14.36",
-        "esbuild-darwin-arm64": "0.14.36",
-        "esbuild-freebsd-64": "0.14.36",
-        "esbuild-freebsd-arm64": "0.14.36",
-        "esbuild-linux-32": "0.14.36",
-        "esbuild-linux-64": "0.14.36",
-        "esbuild-linux-arm": "0.14.36",
-        "esbuild-linux-arm64": "0.14.36",
-        "esbuild-linux-mips64le": "0.14.36",
-        "esbuild-linux-ppc64le": "0.14.36",
-        "esbuild-linux-riscv64": "0.14.36",
-        "esbuild-linux-s390x": "0.14.36",
-        "esbuild-netbsd-64": "0.14.36",
-        "esbuild-openbsd-64": "0.14.36",
-        "esbuild-sunos-64": "0.14.36",
-        "esbuild-windows-32": "0.14.36",
-        "esbuild-windows-64": "0.14.36",
-        "esbuild-windows-arm64": "0.14.36"
+        "esbuild-android-64": "0.14.42",
+        "esbuild-android-arm64": "0.14.42",
+        "esbuild-darwin-64": "0.14.42",
+        "esbuild-darwin-arm64": "0.14.42",
+        "esbuild-freebsd-64": "0.14.42",
+        "esbuild-freebsd-arm64": "0.14.42",
+        "esbuild-linux-32": "0.14.42",
+        "esbuild-linux-64": "0.14.42",
+        "esbuild-linux-arm": "0.14.42",
+        "esbuild-linux-arm64": "0.14.42",
+        "esbuild-linux-mips64le": "0.14.42",
+        "esbuild-linux-ppc64le": "0.14.42",
+        "esbuild-linux-riscv64": "0.14.42",
+        "esbuild-linux-s390x": "0.14.42",
+        "esbuild-netbsd-64": "0.14.42",
+        "esbuild-openbsd-64": "0.14.42",
+        "esbuild-sunos-64": "0.14.42",
+        "esbuild-windows-32": "0.14.42",
+        "esbuild-windows-64": "0.14.42",
+        "esbuild-windows-arm64": "0.14.42"
       }
     },
     "node_modules/esbuild-android-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.36.tgz",
-      "integrity": "sha512-jwpBhF1jmo0tVCYC/ORzVN+hyVcNZUWuozGcLHfod0RJCedTDTvR4nwlTXdx1gtncDqjk33itjO+27OZHbiavw==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.42.tgz",
+      "integrity": "sha512-P4Y36VUtRhK/zivqGVMqhptSrFILAGlYp0Z8r9UQqHJ3iWztRCNWnlBzD9HRx0DbueXikzOiwyOri+ojAFfW6A==",
       "cpu": [
         "x64"
       ],
       }
     },
     "node_modules/esbuild-android-arm64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.36.tgz",
-      "integrity": "sha512-/hYkyFe7x7Yapmfv4X/tBmyKnggUmdQmlvZ8ZlBnV4+PjisrEhAvC3yWpURuD9XoB8Wa1d5dGkTsF53pIvpjsg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.42.tgz",
+      "integrity": "sha512-0cOqCubq+RWScPqvtQdjXG3Czb3AWI2CaKw3HeXry2eoA2rrPr85HF7IpdU26UWdBXgPYtlTN1LUiuXbboROhg==",
       "cpu": [
         "arm64"
       ],
       }
     },
     "node_modules/esbuild-darwin-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.36.tgz",
-      "integrity": "sha512-kkl6qmV0dTpyIMKagluzYqlc1vO0ecgpviK/7jwPbRDEv5fejRTaBBEE2KxEQbTHcLhiiDbhG7d5UybZWo/1zQ==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.42.tgz",
+      "integrity": "sha512-ipiBdCA3ZjYgRfRLdQwP82rTiv/YVMtW36hTvAN5ZKAIfxBOyPXY7Cejp3bMXWgzKD8B6O+zoMzh01GZsCuEIA==",
       "cpu": [
         "x64"
       ],
       }
     },
     "node_modules/esbuild-darwin-arm64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.36.tgz",
-      "integrity": "sha512-q8fY4r2Sx6P0Pr3VUm//eFYKVk07C5MHcEinU1BjyFnuYz4IxR/03uBbDwluR6ILIHnZTE7AkTUWIdidRi1Jjw==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.42.tgz",
+      "integrity": "sha512-bU2tHRqTPOaoH/4m0zYHbFWpiYDmaA0gt90/3BMEFaM0PqVK/a6MA2V/ypV5PO0v8QxN6gH5hBPY4YJ2lopXgA==",
       "cpu": [
         "arm64"
       ],
       }
     },
     "node_modules/esbuild-freebsd-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.36.tgz",
-      "integrity": "sha512-Hn8AYuxXXRptybPqoMkga4HRFE7/XmhtlQjXFHoAIhKUPPMeJH35GYEUWGbjteai9FLFvBAjEAlwEtSGxnqWww==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.42.tgz",
+      "integrity": "sha512-75h1+22Ivy07+QvxHyhVqOdekupiTZVLN1PMwCDonAqyXd8TVNJfIRFrdL8QmSJrOJJ5h8H1I9ETyl2L8LQDaw==",
       "cpu": [
         "x64"
       ],
       }
     },
     "node_modules/esbuild-freebsd-arm64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.36.tgz",
-      "integrity": "sha512-S3C0attylLLRiCcHiJd036eDEMOY32+h8P+jJ3kTcfhJANNjP0TNBNL30TZmEdOSx/820HJFgRrqpNAvTbjnDA==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.42.tgz",
+      "integrity": "sha512-W6Jebeu5TTDQMJUJVarEzRU9LlKpNkPBbjqSu+GUPTHDCly5zZEQq9uHkmHHl7OKm+mQ2zFySN83nmfCeZCyNA==",
       "cpu": [
         "arm64"
       ],
       }
     },
     "node_modules/esbuild-linux-32": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.36.tgz",
-      "integrity": "sha512-Eh9OkyTrEZn9WGO4xkI3OPPpUX7p/3QYvdG0lL4rfr73Ap2HAr6D9lP59VMF64Ex01LhHSXwIsFG/8AQjh6eNw==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.42.tgz",
+      "integrity": "sha512-Ooy/Bj+mJ1z4jlWcK5Dl6SlPlCgQB9zg1UrTCeY8XagvuWZ4qGPyYEWGkT94HUsRi2hKsXvcs6ThTOjBaJSMfg==",
       "cpu": [
         "ia32"
       ],
       }
     },
     "node_modules/esbuild-linux-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.36.tgz",
-      "integrity": "sha512-vFVFS5ve7PuwlfgoWNyRccGDi2QTNkQo/2k5U5ttVD0jRFaMlc8UQee708fOZA6zTCDy5RWsT5MJw3sl2X6KDg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.42.tgz",
+      "integrity": "sha512-2L0HbzQfbTuemUWfVqNIjOfaTRt9zsvjnme6lnr7/MO9toz/MJ5tZhjqrG6uDWDxhsaHI2/nsDgrv8uEEN2eoA==",
       "cpu": [
         "x64"
       ],
       }
     },
     "node_modules/esbuild-linux-arm": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.36.tgz",
-      "integrity": "sha512-NhgU4n+NCsYgt7Hy61PCquEz5aevI6VjQvxwBxtxrooXsxt5b2xtOUXYZe04JxqQo+XZk3d1gcr7pbV9MAQ/Lg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.42.tgz",
+      "integrity": "sha512-STq69yzCMhdRaWnh29UYrLSr/qaWMm/KqwaRF1pMEK7kDiagaXhSL1zQGXbYv94GuGY/zAwzK98+6idCMUOOCg==",
       "cpu": [
         "arm"
       ],
       }
     },
     "node_modules/esbuild-linux-arm64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.36.tgz",
-      "integrity": "sha512-24Vq1M7FdpSmaTYuu1w0Hdhiqkbto1I5Pjyi+4Cdw5fJKGlwQuw+hWynTcRI/cOZxBcBpP21gND7W27gHAiftw==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.42.tgz",
+      "integrity": "sha512-c3Ug3e9JpVr8jAcfbhirtpBauLxzYPpycjWulD71CF6ZSY26tvzmXMJYooQ2YKqDY4e/fPu5K8bm7MiXMnyxuA==",
       "cpu": [
         "arm64"
       ],
       }
     },
     "node_modules/esbuild-linux-mips64le": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.36.tgz",
-      "integrity": "sha512-hZUeTXvppJN+5rEz2EjsOFM9F1bZt7/d2FUM1lmQo//rXh1RTFYzhC0txn7WV0/jCC7SvrGRaRz0NMsRPf8SIA==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.42.tgz",
+      "integrity": "sha512-QuvpHGbYlkyXWf2cGm51LBCHx6eUakjaSrRpUqhPwjh/uvNUYvLmz2LgPTTPwCqaKt0iwL+OGVL0tXA5aDbAbg==",
       "cpu": [
         "mips64el"
       ],
       }
     },
     "node_modules/esbuild-linux-ppc64le": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.36.tgz",
-      "integrity": "sha512-1Bg3QgzZjO+QtPhP9VeIBhAduHEc2kzU43MzBnMwpLSZ890azr4/A9Dganun8nsqD/1TBcqhId0z4mFDO8FAvg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.42.tgz",
+      "integrity": "sha512-8ohIVIWDbDT+i7lCx44YCyIRrOW1MYlks9fxTo0ME2LS/fxxdoJBwHWzaDYhjvf8kNpA+MInZvyOEAGoVDrMHg==",
       "cpu": [
         "ppc64"
       ],
       }
     },
     "node_modules/esbuild-linux-riscv64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.36.tgz",
-      "integrity": "sha512-dOE5pt3cOdqEhaufDRzNCHf5BSwxgygVak9UR7PH7KPVHwSTDAZHDoEjblxLqjJYpc5XaU9+gKJ9F8mp9r5I4A==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.42.tgz",
+      "integrity": "sha512-DzDqK3TuoXktPyG1Lwx7vhaF49Onv3eR61KwQyxYo4y5UKTpL3NmuarHSIaSVlTFDDpcIajCDwz5/uwKLLgKiQ==",
       "cpu": [
         "riscv64"
       ],
       }
     },
     "node_modules/esbuild-linux-s390x": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.36.tgz",
-      "integrity": "sha512-g4FMdh//BBGTfVHjF6MO7Cz8gqRoDPzXWxRvWkJoGroKA18G9m0wddvPbEqcQf5Tbt2vSc1CIgag7cXwTmoTXg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.42.tgz",
+      "integrity": "sha512-YFRhPCxl8nb//Wn6SiS5pmtplBi4z9yC2gLrYoYI/tvwuB1jldir9r7JwAGy1Ck4D7sE7wBN9GFtUUX/DLdcEQ==",
       "cpu": [
         "s390x"
       ],
       }
     },
     "node_modules/esbuild-netbsd-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.36.tgz",
-      "integrity": "sha512-UB2bVImxkWk4vjnP62ehFNZ73lQY1xcnL5ZNYF3x0AG+j8HgdkNF05v67YJdCIuUJpBuTyCK8LORCYo9onSW+A==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.42.tgz",
+      "integrity": "sha512-QYSD2k+oT9dqB/4eEM9c+7KyNYsIPgzYOSrmfNGDIyJrbT1d+CFVKvnKahDKNJLfOYj8N4MgyFaU9/Ytc6w5Vw==",
       "cpu": [
         "x64"
       ],
       }
     },
     "node_modules/esbuild-openbsd-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.36.tgz",
-      "integrity": "sha512-NvGB2Chf8GxuleXRGk8e9zD3aSdRO5kLt9coTQbCg7WMGXeX471sBgh4kSg8pjx0yTXRt0MlrUDnjVYnetyivg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.42.tgz",
+      "integrity": "sha512-M2meNVIKWsm2HMY7+TU9AxM7ZVwI9havdsw6m/6EzdXysyCFFSoaTQ/Jg03izjCsK17FsVRHqRe26Llj6x0MNA==",
       "cpu": [
         "x64"
       ],
       }
     },
     "node_modules/esbuild-sunos-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.36.tgz",
-      "integrity": "sha512-VkUZS5ftTSjhRjuRLp+v78auMO3PZBXu6xl4ajomGenEm2/rGuWlhFSjB7YbBNErOchj51Jb2OK8lKAo8qdmsQ==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.42.tgz",
+      "integrity": "sha512-uXV8TAZEw36DkgW8Ak3MpSJs1ofBb3Smkc/6pZ29sCAN1KzCAQzsje4sUwugf+FVicrHvlamCOlFZIXgct+iqQ==",
       "cpu": [
         "x64"
       ],
       }
     },
     "node_modules/esbuild-windows-32": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.36.tgz",
-      "integrity": "sha512-bIar+A6hdytJjZrDxfMBUSEHHLfx3ynoEZXx/39nxy86pX/w249WZm8Bm0dtOAByAf4Z6qV0LsnTIJHiIqbw0w==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.42.tgz",
+      "integrity": "sha512-4iw/8qWmRICWi9ZOnJJf9sYt6wmtp3hsN4TdI5NqgjfOkBVMxNdM9Vt3626G1Rda9ya2Q0hjQRD9W1o+m6Lz6g==",
       "cpu": [
         "ia32"
       ],
       }
     },
     "node_modules/esbuild-windows-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.36.tgz",
-      "integrity": "sha512-+p4MuRZekVChAeueT1Y9LGkxrT5x7YYJxYE8ZOTcEfeUUN43vktSn6hUNsvxzzATrSgq5QqRdllkVBxWZg7KqQ==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.42.tgz",
+      "integrity": "sha512-j3cdK+Y3+a5H0wHKmLGTJcq0+/2mMBHPWkItR3vytp/aUGD/ua/t2BLdfBIzbNN9nLCRL9sywCRpOpFMx3CxzA==",
       "cpu": [
         "x64"
       ],
       }
     },
     "node_modules/esbuild-windows-arm64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.36.tgz",
-      "integrity": "sha512-fBB4WlDqV1m18EF/aheGYQkQZHfPHiHJSBYzXIo8yKehek+0BtBwo/4PNwKGJ5T0YK0oc8pBKjgwPbzSrPLb+Q==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.42.tgz",
+      "integrity": "sha512-+lRAARnF+hf8J0mN27ujO+VbhPbDqJ8rCcJKye4y7YZLV6C4n3pTRThAb388k/zqF5uM0lS5O201u0OqoWSicw==",
       "cpu": [
         "arm64"
       ],
       "dev": true
     },
     "node_modules/linkify-it": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
-      "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz",
+      "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==",
       "dependencies": {
         "uc.micro": "^1.0.1"
       }
       "dev": true
     },
     "node_modules/markdown-it": {
-      "version": "12.3.2",
-      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
-      "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
+      "version": "13.0.1",
+      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz",
+      "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==",
       "dependencies": {
         "argparse": "^2.0.1",
-        "entities": "~2.1.0",
-        "linkify-it": "^3.0.1",
+        "entities": "~3.0.1",
+        "linkify-it": "^4.0.1",
         "mdurl": "^1.0.1",
         "uc.micro": "^1.0.5"
       },
       }
     },
     "node_modules/sass": {
-      "version": "1.50.0",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.50.0.tgz",
-      "integrity": "sha512-cLsD6MEZ5URXHStxApajEh7gW189kkjn4Rc8DQweMyF+o5HF5nfEz8QYLMlPsTOD88DknatTmBWkOcw5/LnJLQ==",
+      "version": "1.52.1",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.1.tgz",
+      "integrity": "sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q==",
       "dev": true,
       "dependencies": {
         "chokidar": ">=3.0.0 <4.0.0",
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/snabbdom": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.5.0.tgz",
+      "integrity": "sha512-Ff5BKG18KrrPuskHJlA9aujPHqEabItaDl96l7ZZndF4zt5AYSczz7ZjjgQAX5IBd5cd25lw9NfgX21yVUJ+9g==",
+      "engines": {
+        "node": ">=8.3.0"
+      }
+    },
     "node_modules/sortablejs": {
       "version": "1.15.0",
       "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
       }
     },
     "clipboard": {
-      "version": "2.0.10",
-      "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.10.tgz",
-      "integrity": "sha512-cz3m2YVwFz95qSEbCDi2fzLN/epEN9zXBvfgAoGkvGOJZATMl9gtTDVOtBYkx2ODUJl2kvmud7n32sV2BpYR4g==",
+      "version": "2.0.11",
+      "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz",
+      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
       "requires": {
         "good-listener": "^1.2.2",
         "select": "^1.1.2",
       }
     },
     "codemirror": {
-      "version": "5.65.2",
-      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.2.tgz",
-      "integrity": "sha512-SZM4Zq7XEC8Fhroqe3LxbEEX1zUPWH1wMr5zxiBuiUF64iYOUH/JI88v4tBag8MiBS8B8gRv8O1pPXGYXQ4ErA=="
+      "version": "5.65.5",
+      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.5.tgz",
+      "integrity": "sha512-HNyhvGLnYz5c+kIsB9QKVitiZUevha3ovbIYaQiGzKo7ECSL/elWD9RXt3JgNr0NdnyqE9/Rc/7uLfkJQL638w=="
     },
     "color-convert": {
       "version": "1.9.3",
       "dev": true
     },
     "entities": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
-      "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w=="
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
+      "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q=="
     },
     "error-ex": {
       "version": "1.3.2",
       }
     },
     "esbuild": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.36.tgz",
-      "integrity": "sha512-HhFHPiRXGYOCRlrhpiVDYKcFJRdO0sBElZ668M4lh2ER0YgnkLxECuFe7uWCf23FrcLc59Pqr7dHkTqmRPDHmw==",
-      "dev": true,
-      "requires": {
-        "esbuild-android-64": "0.14.36",
-        "esbuild-android-arm64": "0.14.36",
-        "esbuild-darwin-64": "0.14.36",
-        "esbuild-darwin-arm64": "0.14.36",
-        "esbuild-freebsd-64": "0.14.36",
-        "esbuild-freebsd-arm64": "0.14.36",
-        "esbuild-linux-32": "0.14.36",
-        "esbuild-linux-64": "0.14.36",
-        "esbuild-linux-arm": "0.14.36",
-        "esbuild-linux-arm64": "0.14.36",
-        "esbuild-linux-mips64le": "0.14.36",
-        "esbuild-linux-ppc64le": "0.14.36",
-        "esbuild-linux-riscv64": "0.14.36",
-        "esbuild-linux-s390x": "0.14.36",
-        "esbuild-netbsd-64": "0.14.36",
-        "esbuild-openbsd-64": "0.14.36",
-        "esbuild-sunos-64": "0.14.36",
-        "esbuild-windows-32": "0.14.36",
-        "esbuild-windows-64": "0.14.36",
-        "esbuild-windows-arm64": "0.14.36"
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.42.tgz",
+      "integrity": "sha512-V0uPZotCEHokJdNqyozH6qsaQXqmZEOiZWrXnds/zaH/0SyrIayRXWRB98CENO73MIZ9T3HBIOsmds5twWtmgw==",
+      "dev": true,
+      "requires": {
+        "esbuild-android-64": "0.14.42",
+        "esbuild-android-arm64": "0.14.42",
+        "esbuild-darwin-64": "0.14.42",
+        "esbuild-darwin-arm64": "0.14.42",
+        "esbuild-freebsd-64": "0.14.42",
+        "esbuild-freebsd-arm64": "0.14.42",
+        "esbuild-linux-32": "0.14.42",
+        "esbuild-linux-64": "0.14.42",
+        "esbuild-linux-arm": "0.14.42",
+        "esbuild-linux-arm64": "0.14.42",
+        "esbuild-linux-mips64le": "0.14.42",
+        "esbuild-linux-ppc64le": "0.14.42",
+        "esbuild-linux-riscv64": "0.14.42",
+        "esbuild-linux-s390x": "0.14.42",
+        "esbuild-netbsd-64": "0.14.42",
+        "esbuild-openbsd-64": "0.14.42",
+        "esbuild-sunos-64": "0.14.42",
+        "esbuild-windows-32": "0.14.42",
+        "esbuild-windows-64": "0.14.42",
+        "esbuild-windows-arm64": "0.14.42"
       }
     },
     "esbuild-android-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.36.tgz",
-      "integrity": "sha512-jwpBhF1jmo0tVCYC/ORzVN+hyVcNZUWuozGcLHfod0RJCedTDTvR4nwlTXdx1gtncDqjk33itjO+27OZHbiavw==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.42.tgz",
+      "integrity": "sha512-P4Y36VUtRhK/zivqGVMqhptSrFILAGlYp0Z8r9UQqHJ3iWztRCNWnlBzD9HRx0DbueXikzOiwyOri+ojAFfW6A==",
       "dev": true,
       "optional": true
     },
     "esbuild-android-arm64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.36.tgz",
-      "integrity": "sha512-/hYkyFe7x7Yapmfv4X/tBmyKnggUmdQmlvZ8ZlBnV4+PjisrEhAvC3yWpURuD9XoB8Wa1d5dGkTsF53pIvpjsg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.42.tgz",
+      "integrity": "sha512-0cOqCubq+RWScPqvtQdjXG3Czb3AWI2CaKw3HeXry2eoA2rrPr85HF7IpdU26UWdBXgPYtlTN1LUiuXbboROhg==",
       "dev": true,
       "optional": true
     },
     "esbuild-darwin-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.36.tgz",
-      "integrity": "sha512-kkl6qmV0dTpyIMKagluzYqlc1vO0ecgpviK/7jwPbRDEv5fejRTaBBEE2KxEQbTHcLhiiDbhG7d5UybZWo/1zQ==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.42.tgz",
+      "integrity": "sha512-ipiBdCA3ZjYgRfRLdQwP82rTiv/YVMtW36hTvAN5ZKAIfxBOyPXY7Cejp3bMXWgzKD8B6O+zoMzh01GZsCuEIA==",
       "dev": true,
       "optional": true
     },
     "esbuild-darwin-arm64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.36.tgz",
-      "integrity": "sha512-q8fY4r2Sx6P0Pr3VUm//eFYKVk07C5MHcEinU1BjyFnuYz4IxR/03uBbDwluR6ILIHnZTE7AkTUWIdidRi1Jjw==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.42.tgz",
+      "integrity": "sha512-bU2tHRqTPOaoH/4m0zYHbFWpiYDmaA0gt90/3BMEFaM0PqVK/a6MA2V/ypV5PO0v8QxN6gH5hBPY4YJ2lopXgA==",
       "dev": true,
       "optional": true
     },
     "esbuild-freebsd-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.36.tgz",
-      "integrity": "sha512-Hn8AYuxXXRptybPqoMkga4HRFE7/XmhtlQjXFHoAIhKUPPMeJH35GYEUWGbjteai9FLFvBAjEAlwEtSGxnqWww==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.42.tgz",
+      "integrity": "sha512-75h1+22Ivy07+QvxHyhVqOdekupiTZVLN1PMwCDonAqyXd8TVNJfIRFrdL8QmSJrOJJ5h8H1I9ETyl2L8LQDaw==",
       "dev": true,
       "optional": true
     },
     "esbuild-freebsd-arm64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.36.tgz",
-      "integrity": "sha512-S3C0attylLLRiCcHiJd036eDEMOY32+h8P+jJ3kTcfhJANNjP0TNBNL30TZmEdOSx/820HJFgRrqpNAvTbjnDA==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.42.tgz",
+      "integrity": "sha512-W6Jebeu5TTDQMJUJVarEzRU9LlKpNkPBbjqSu+GUPTHDCly5zZEQq9uHkmHHl7OKm+mQ2zFySN83nmfCeZCyNA==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-32": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.36.tgz",
-      "integrity": "sha512-Eh9OkyTrEZn9WGO4xkI3OPPpUX7p/3QYvdG0lL4rfr73Ap2HAr6D9lP59VMF64Ex01LhHSXwIsFG/8AQjh6eNw==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.42.tgz",
+      "integrity": "sha512-Ooy/Bj+mJ1z4jlWcK5Dl6SlPlCgQB9zg1UrTCeY8XagvuWZ4qGPyYEWGkT94HUsRi2hKsXvcs6ThTOjBaJSMfg==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.36.tgz",
-      "integrity": "sha512-vFVFS5ve7PuwlfgoWNyRccGDi2QTNkQo/2k5U5ttVD0jRFaMlc8UQee708fOZA6zTCDy5RWsT5MJw3sl2X6KDg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.42.tgz",
+      "integrity": "sha512-2L0HbzQfbTuemUWfVqNIjOfaTRt9zsvjnme6lnr7/MO9toz/MJ5tZhjqrG6uDWDxhsaHI2/nsDgrv8uEEN2eoA==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-arm": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.36.tgz",
-      "integrity": "sha512-NhgU4n+NCsYgt7Hy61PCquEz5aevI6VjQvxwBxtxrooXsxt5b2xtOUXYZe04JxqQo+XZk3d1gcr7pbV9MAQ/Lg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.42.tgz",
+      "integrity": "sha512-STq69yzCMhdRaWnh29UYrLSr/qaWMm/KqwaRF1pMEK7kDiagaXhSL1zQGXbYv94GuGY/zAwzK98+6idCMUOOCg==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-arm64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.36.tgz",
-      "integrity": "sha512-24Vq1M7FdpSmaTYuu1w0Hdhiqkbto1I5Pjyi+4Cdw5fJKGlwQuw+hWynTcRI/cOZxBcBpP21gND7W27gHAiftw==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.42.tgz",
+      "integrity": "sha512-c3Ug3e9JpVr8jAcfbhirtpBauLxzYPpycjWulD71CF6ZSY26tvzmXMJYooQ2YKqDY4e/fPu5K8bm7MiXMnyxuA==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-mips64le": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.36.tgz",
-      "integrity": "sha512-hZUeTXvppJN+5rEz2EjsOFM9F1bZt7/d2FUM1lmQo//rXh1RTFYzhC0txn7WV0/jCC7SvrGRaRz0NMsRPf8SIA==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.42.tgz",
+      "integrity": "sha512-QuvpHGbYlkyXWf2cGm51LBCHx6eUakjaSrRpUqhPwjh/uvNUYvLmz2LgPTTPwCqaKt0iwL+OGVL0tXA5aDbAbg==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-ppc64le": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.36.tgz",
-      "integrity": "sha512-1Bg3QgzZjO+QtPhP9VeIBhAduHEc2kzU43MzBnMwpLSZ890azr4/A9Dganun8nsqD/1TBcqhId0z4mFDO8FAvg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.42.tgz",
+      "integrity": "sha512-8ohIVIWDbDT+i7lCx44YCyIRrOW1MYlks9fxTo0ME2LS/fxxdoJBwHWzaDYhjvf8kNpA+MInZvyOEAGoVDrMHg==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-riscv64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.36.tgz",
-      "integrity": "sha512-dOE5pt3cOdqEhaufDRzNCHf5BSwxgygVak9UR7PH7KPVHwSTDAZHDoEjblxLqjJYpc5XaU9+gKJ9F8mp9r5I4A==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.42.tgz",
+      "integrity": "sha512-DzDqK3TuoXktPyG1Lwx7vhaF49Onv3eR61KwQyxYo4y5UKTpL3NmuarHSIaSVlTFDDpcIajCDwz5/uwKLLgKiQ==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-s390x": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.36.tgz",
-      "integrity": "sha512-g4FMdh//BBGTfVHjF6MO7Cz8gqRoDPzXWxRvWkJoGroKA18G9m0wddvPbEqcQf5Tbt2vSc1CIgag7cXwTmoTXg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.42.tgz",
+      "integrity": "sha512-YFRhPCxl8nb//Wn6SiS5pmtplBi4z9yC2gLrYoYI/tvwuB1jldir9r7JwAGy1Ck4D7sE7wBN9GFtUUX/DLdcEQ==",
       "dev": true,
       "optional": true
     },
     "esbuild-netbsd-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.36.tgz",
-      "integrity": "sha512-UB2bVImxkWk4vjnP62ehFNZ73lQY1xcnL5ZNYF3x0AG+j8HgdkNF05v67YJdCIuUJpBuTyCK8LORCYo9onSW+A==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.42.tgz",
+      "integrity": "sha512-QYSD2k+oT9dqB/4eEM9c+7KyNYsIPgzYOSrmfNGDIyJrbT1d+CFVKvnKahDKNJLfOYj8N4MgyFaU9/Ytc6w5Vw==",
       "dev": true,
       "optional": true
     },
     "esbuild-openbsd-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.36.tgz",
-      "integrity": "sha512-NvGB2Chf8GxuleXRGk8e9zD3aSdRO5kLt9coTQbCg7WMGXeX471sBgh4kSg8pjx0yTXRt0MlrUDnjVYnetyivg==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.42.tgz",
+      "integrity": "sha512-M2meNVIKWsm2HMY7+TU9AxM7ZVwI9havdsw6m/6EzdXysyCFFSoaTQ/Jg03izjCsK17FsVRHqRe26Llj6x0MNA==",
       "dev": true,
       "optional": true
     },
     "esbuild-sunos-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.36.tgz",
-      "integrity": "sha512-VkUZS5ftTSjhRjuRLp+v78auMO3PZBXu6xl4ajomGenEm2/rGuWlhFSjB7YbBNErOchj51Jb2OK8lKAo8qdmsQ==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.42.tgz",
+      "integrity": "sha512-uXV8TAZEw36DkgW8Ak3MpSJs1ofBb3Smkc/6pZ29sCAN1KzCAQzsje4sUwugf+FVicrHvlamCOlFZIXgct+iqQ==",
       "dev": true,
       "optional": true
     },
     "esbuild-windows-32": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.36.tgz",
-      "integrity": "sha512-bIar+A6hdytJjZrDxfMBUSEHHLfx3ynoEZXx/39nxy86pX/w249WZm8Bm0dtOAByAf4Z6qV0LsnTIJHiIqbw0w==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.42.tgz",
+      "integrity": "sha512-4iw/8qWmRICWi9ZOnJJf9sYt6wmtp3hsN4TdI5NqgjfOkBVMxNdM9Vt3626G1Rda9ya2Q0hjQRD9W1o+m6Lz6g==",
       "dev": true,
       "optional": true
     },
     "esbuild-windows-64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.36.tgz",
-      "integrity": "sha512-+p4MuRZekVChAeueT1Y9LGkxrT5x7YYJxYE8ZOTcEfeUUN43vktSn6hUNsvxzzATrSgq5QqRdllkVBxWZg7KqQ==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.42.tgz",
+      "integrity": "sha512-j3cdK+Y3+a5H0wHKmLGTJcq0+/2mMBHPWkItR3vytp/aUGD/ua/t2BLdfBIzbNN9nLCRL9sywCRpOpFMx3CxzA==",
       "dev": true,
       "optional": true
     },
     "esbuild-windows-arm64": {
-      "version": "0.14.36",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.36.tgz",
-      "integrity": "sha512-fBB4WlDqV1m18EF/aheGYQkQZHfPHiHJSBYzXIo8yKehek+0BtBwo/4PNwKGJ5T0YK0oc8pBKjgwPbzSrPLb+Q==",
+      "version": "0.14.42",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.42.tgz",
+      "integrity": "sha512-+lRAARnF+hf8J0mN27ujO+VbhPbDqJ8rCcJKye4y7YZLV6C4n3pTRThAb388k/zqF5uM0lS5O201u0OqoWSicw==",
       "dev": true,
       "optional": true
     },
       "dev": true
     },
     "linkify-it": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
-      "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz",
+      "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==",
       "requires": {
         "uc.micro": "^1.0.1"
       }
       "dev": true
     },
     "markdown-it": {
-      "version": "12.3.2",
-      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
-      "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
+      "version": "13.0.1",
+      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz",
+      "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==",
       "requires": {
         "argparse": "^2.0.1",
-        "entities": "~2.1.0",
-        "linkify-it": "^3.0.1",
+        "entities": "~3.0.1",
+        "linkify-it": "^4.0.1",
         "mdurl": "^1.0.1",
         "uc.micro": "^1.0.5"
       }
       }
     },
     "sass": {
-      "version": "1.50.0",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.50.0.tgz",
-      "integrity": "sha512-cLsD6MEZ5URXHStxApajEh7gW189kkjn4Rc8DQweMyF+o5HF5nfEz8QYLMlPsTOD88DknatTmBWkOcw5/LnJLQ==",
+      "version": "1.52.1",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.1.tgz",
+      "integrity": "sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q==",
       "dev": true,
       "requires": {
         "chokidar": ">=3.0.0 <4.0.0",
         "object-inspect": "^1.9.0"
       }
     },
+    "snabbdom": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.5.0.tgz",
+      "integrity": "sha512-Ff5BKG18KrrPuskHJlA9aujPHqEabItaDl96l7ZZndF4zt5AYSczz7ZjjgQAX5IBd5cd25lw9NfgX21yVUJ+9g=="
+    },
     "sortablejs": {
       "version": "1.15.0",
       "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
index b49a2a07f32b7196b7c8d1c503529adfa51eb0b4..9a2f664482a08958a2ae1d3e72fcce593e40c6bd 100644 (file)
@@ -1,8 +1,8 @@
 {
   "private": true,
   "scripts": {
-    "build:css:dev": "sass ./resources/sass:./public/dist",
-    "build:css:watch": "sass ./resources/sass:./public/dist --watch",
+    "build:css:dev": "sass ./resources/sass:./public/dist --embed-sources",
+    "build:css:watch": "sass ./resources/sass:./public/dist --watch --embed-sources",
     "build:css:production": "sass ./resources/sass:./public/dist -s compressed",
     "build:js:dev": "node dev/build/esbuild.js",
     "build:js:watch": "chokidar --initial \"./resources/**/*.js\" -c \"npm run build:js:dev\"",
   },
   "devDependencies": {
     "chokidar-cli": "^3.0",
-    "esbuild": "0.14.36",
+    "esbuild": "0.14.42",
     "livereload": "^0.9.3",
     "npm-run-all": "^4.1.5",
     "punycode": "^2.1.1",
-    "sass": "^1.50.0"
+    "sass": "^1.52.1"
   },
   "dependencies": {
-    "clipboard": "^2.0.10",
-    "codemirror": "^5.65.2",
+    "clipboard": "^2.0.11",
+    "codemirror": "^5.65.5",
     "dropzone": "^5.9.3",
-    "markdown-it": "^12.3.2",
+    "markdown-it": "^13.0.1",
     "markdown-it-task-lists": "^2.1.1",
+    "snabbdom": "^3.5.0",
     "sortablejs": "^1.15.0"
   }
 }
index 90320ff41971661f47b2cc4836f5ffa4ada955fb..56a510b101d14fb28a140128ef48ef0a99418732 100644 (file)
@@ -29,6 +29,7 @@
     <server name="MAIL_DRIVER" value="array"/>
     <server name="LOG_CHANNEL" value="single"/>
     <server name="AUTH_METHOD" value="standard"/>
+    <server name="AUTH_AUTO_INITIATE" value="false"/>
     <server name="DISABLE_EXTERNAL_SERVICES" value="true"/>
     <server name="ALLOW_UNTRUSTED_SERVER_FETCHING" value="false"/>
     <server name="AVATAR_URL" value=""/>
diff --git a/resources/icons/download.svg b/resources/icons/download.svg
new file mode 100644 (file)
index 0000000..6299571
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M16.59 9H15V4c0-.55-.45-1-1-1h-4c-.55 0-1 .45-1 1v5H7.41c-.89 0-1.34 1.08-.71 1.71l4.59 4.59c.39.39 1.02.39 1.41 0l4.59-4.59c.63-.63.19-1.71-.7-1.71zM5 19c0 .55.45 1 1 1h12c.55 0 1-.45 1-1s-.45-1-1-1H6c-.55 0-1 .45-1 1z"/></svg>
\ No newline at end of file
index 8e2ed72c89be270ba268d907ac38da6bd1587fce..5d4186dd0527abaa4257edce8e50312bd4c65c7f 100644 (file)
@@ -25,6 +25,7 @@ import 'codemirror/mode/ruby/ruby';
 import 'codemirror/mode/rust/rust';
 import 'codemirror/mode/shell/shell';
 import 'codemirror/mode/sql/sql';
+import 'codemirror/mode/stex/stex';
 import 'codemirror/mode/toml/toml';
 import 'codemirror/mode/vb/vb';
 import 'codemirror/mode/vbscript/vbscript';
@@ -49,16 +50,19 @@ const modeMap = {
     diff: 'diff',
     for: 'fortran',
     fortran: 'fortran',
+    'f#': 'text/x-fsharp',
+    fsharp: 'text/x-fsharp',
     go: 'go',
     haskell: 'haskell',
     hs: 'haskell',
     html: 'htmlmixed',
     ini: 'properties',
-    javascript: 'javascript',
-    json: {name: 'javascript', json: true},
-    js: 'javascript',
-    jl: 'julia',
-    julia: 'julia',
+    javascript: 'text/javascript',
+    json: 'application/json',
+    js: 'text/javascript',
+    jl: 'text/x-julia',
+    julia: 'text/x-julia',
+    latex: 'text/x-stex',
     lua: 'lua',
     md: 'markdown',
     mdown: 'markdown',
@@ -69,7 +73,7 @@ const modeMap = {
     pl: 'perl',
     powershell: 'powershell',
     properties: 'properties',
-    ocaml: 'mllike',
+    ocaml: 'text/x-ocaml',
     pascal: 'text/x-pascal',
     pas: 'text/x-pascal',
     php: (content) => {
@@ -83,8 +87,11 @@ const modeMap = {
     rs: 'rust',
     shell: 'shell',
     sh: 'shell',
+    stext: 'text/x-stex',
     bash: 'shell',
     toml: 'toml',
+    ts: 'text/typescript',
+    typescript: 'text/typescript',
     sql: 'text/x-sql',
     vbs: 'vbscript',
     vbscript: 'vbscript',
@@ -242,6 +249,21 @@ export function popupEditor(elem, modeSuggestion) {
     });
 }
 
+/**
+ * Create an inline editor to replace the given textarea.
+ * @param {HTMLTextAreaElement} textArea
+ * @param {String} mode
+ * @returns {CodeMirror3}
+ */
+export function inlineEditor(textArea, mode) {
+    return CodeMirror.fromTextArea(textArea, {
+        mode: getMode(mode, textArea.value),
+        lineNumbers: true,
+        lineWrapping: false,
+        theme: getTheme(),
+    });
+}
+
 /**
  * Set the mode of a codemirror instance.
  * @param cmInstance
diff --git a/resources/js/components/chapter-contents.js b/resources/js/components/chapter-contents.js
new file mode 100644 (file)
index 0000000..c824d0f
--- /dev/null
@@ -0,0 +1,37 @@
+import {slideUp, slideDown} from "../services/animations";
+
+/**
+ * @extends {Component}
+ */
+class ChapterContents {
+
+    setup() {
+        this.list = this.$refs.list;
+        this.toggle = this.$refs.toggle;
+
+        this.isOpen = this.toggle.classList.contains('open');
+        this.toggle.addEventListener('click', this.click.bind(this));
+    }
+
+    open() {
+        this.toggle.classList.add('open');
+        this.toggle.setAttribute('aria-expanded', 'true');
+        slideDown(this.list, 180);
+        this.isOpen = true;
+    }
+
+    close() {
+        this.toggle.classList.remove('open');
+        this.toggle.setAttribute('aria-expanded', 'false');
+        slideUp(this.list, 180);
+        this.isOpen = false;
+    }
+
+    click(event) {
+        event.preventDefault();
+        this.isOpen ?  this.close() : this.open();
+    }
+
+}
+
+export default ChapterContents;
diff --git a/resources/js/components/chapter-toggle.js b/resources/js/components/chapter-toggle.js
deleted file mode 100644 (file)
index bfd0ac7..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-import {slideUp, slideDown} from "../services/animations";
-
-class ChapterToggle {
-
-    constructor(elem) {
-        this.elem = elem;
-        this.isOpen = elem.classList.contains('open');
-        elem.addEventListener('click', this.click.bind(this));
-    }
-
-    open() {
-        const list = this.elem.parentNode.querySelector('.inset-list');
-        this.elem.classList.add('open');
-        this.elem.setAttribute('aria-expanded', 'true');
-        slideDown(list, 240);
-    }
-
-    close() {
-        const list = this.elem.parentNode.querySelector('.inset-list');
-        this.elem.classList.remove('open');
-        this.elem.setAttribute('aria-expanded', 'false');
-        slideUp(list, 240);
-    }
-
-    click(event) {
-        event.preventDefault();
-        this.isOpen ?  this.close() : this.open();
-        this.isOpen = !this.isOpen;
-    }
-
-}
-
-export default ChapterToggle;
index 4ee3531c58a7da957079a7a9ffb6c46aaaaf9c4c..27ff56395d1af49968014407f77c31d1b96e6c3c 100644 (file)
@@ -33,10 +33,11 @@ class CodeEditor {
         onSelect(this.languageLinks, event => {
             const language = event.target.dataset.lang;
             this.languageInput.value = language;
-            this.updateEditorMode(language);
+            this.languageInputChange(language);
         });
 
         onEnterPress(this.languageInput, e => this.save());
+        this.languageInput.addEventListener('input', e => this.languageInputChange(this.languageInput.value));
         onSelect(this.saveButton, e => this.save());
 
         onChildEvent(this.historyList, 'button', 'click', (event, elem) => {
@@ -60,7 +61,7 @@ class CodeEditor {
         this.callback = callback;
 
         this.show()
-            .then(() => this.updateEditorMode(language))
+            .then(() => this.languageInputChange(language))
             .then(() => window.importVersioned('code'))
             .then(Code => Code.setContent(this.editor, code));
     }
@@ -90,6 +91,22 @@ class CodeEditor {
         Code.setMode(this.editor, language, this.editor.getValue());
     }
 
+    languageInputChange(language) {
+        this.updateEditorMode(language);
+        const inputLang = language.toLowerCase();
+        let matched = false;
+
+        for (const link of this.languageLinks) {
+            const lang = link.dataset.lang.toLowerCase().trim();
+            const isMatch = inputLang && lang.startsWith(inputLang);
+            link.classList.toggle('active', isMatch);
+            if (isMatch && !matched) {
+                link.scrollIntoView({block: "center", behavior: "smooth"});
+                matched = true;
+            }
+        }
+    }
+
     loadHistory() {
         this.history = JSON.parse(window.sessionStorage.getItem(this.historyKey) || '{}');
         const historyKeys = Object.keys(this.history).reverse();
diff --git a/resources/js/components/code-textarea.js b/resources/js/components/code-textarea.js
new file mode 100644 (file)
index 0000000..988e51f
--- /dev/null
@@ -0,0 +1,16 @@
+/**
+ * A simple component to render a code editor within the textarea
+ * this exists upon.
+ * @extends {Component}
+ */
+class CodeTextarea {
+
+    async setup() {
+        const mode = this.$opts.mode;
+        const Code = await window.importVersioned('code');
+        Code.inlineEditor(this.$el, mode);
+    }
+
+}
+
+export default CodeTextarea;
\ No newline at end of file
index e2d55f9694ded7b9d938050f563fad4791a93cb4..81fa940c24ca7cf4a38ba66fe7b55e300d746100 100644 (file)
@@ -1,4 +1,5 @@
 import {debounce} from "../services/util";
+import {transitionHeight} from "../services/animations";
 
 class DropdownSearch {
 
@@ -51,7 +52,9 @@ class DropdownSearch {
 
         try {
             const resp = await window.$http.get(this.getAjaxUrl(searchTerm));
+            const animate = transitionHeight(this.listContainerElem, 80);
             this.listContainerElem.innerHTML = resp.data;
+            animate();
         } catch (err) {
             console.error(err);
         }
index f761ecf011541590963caf66daf4b145f43c8cde..473db37d43f666660d7276e1790a1bc47d101b20 100644 (file)
@@ -28,18 +28,31 @@ class DropDown {
         this.menu.classList.add('anim', 'menuIn');
         this.toggle.setAttribute('aria-expanded', 'true');
 
+        const menuOriginalRect = this.menu.getBoundingClientRect();
+        let heightOffset = 0;
+        const toggleHeight = this.toggle.getBoundingClientRect().height;
+        const dropUpwards = menuOriginalRect.bottom > window.innerHeight;
+
+        // If enabled, Move to body to prevent being trapped within scrollable sections
         if (this.moveMenu) {
-            // Move to body to prevent being trapped within scrollable sections
-            this.rect = this.menu.getBoundingClientRect();
             this.body.appendChild(this.menu);
             this.menu.style.position = 'fixed';
             if (this.direction === 'right') {
-                this.menu.style.right = `${(this.rect.right - this.rect.width)}px`;
+                this.menu.style.right = `${(menuOriginalRect.right - menuOriginalRect.width)}px`;
             } else {
-                this.menu.style.left = `${this.rect.left}px`;
+                this.menu.style.left = `${menuOriginalRect.left}px`;
             }
-            this.menu.style.top = `${this.rect.top}px`;
-            this.menu.style.width = `${this.rect.width}px`;
+            this.menu.style.width = `${menuOriginalRect.width}px`;
+            heightOffset = dropUpwards ? (window.innerHeight - menuOriginalRect.top  - toggleHeight / 2) : menuOriginalRect.top;
+        }
+
+        // Adjust menu to display upwards if near the bottom of the screen
+        if (dropUpwards) {
+            this.menu.style.top = 'initial';
+            this.menu.style.bottom = `${heightOffset}px`;
+        } else {
+            this.menu.style.top = `${heightOffset}px`;
+            this.menu.style.bottom = 'initial';
         }
 
         // Set listener to hide on mouse leave or window click
@@ -74,18 +87,21 @@ class DropDown {
         this.menu.style.display = 'none';
         this.menu.classList.remove('anim', 'menuIn');
         this.toggle.setAttribute('aria-expanded', 'false');
+        this.menu.style.top = '';
+        this.menu.style.bottom = '';
+
         if (this.moveMenu) {
             this.menu.style.position = '';
             this.menu.style[this.direction] = '';
-            this.menu.style.top = '';
             this.menu.style.width = '';
             this.container.appendChild(this.menu);
         }
+
         this.showing = false;
     }
 
     getFocusable() {
-        return Array.from(this.menu.querySelectorAll('[tabindex],[href],button,input:not([type=hidden])'));
+        return Array.from(this.menu.querySelectorAll('[tabindex]:not([tabindex="-1"]),[href],button,input:not([type=hidden])'));
     }
 
     focusNext() {
index 6a4a8c2b08fc9096380fc225f361e28196883150..f360e2b0c2b57e2178e4716df96513a36ed3d220 100644 (file)
@@ -6,9 +6,10 @@ import attachmentsList from "./attachments-list.js"
 import autoSuggest from "./auto-suggest.js"
 import backToTop from "./back-to-top.js"
 import bookSort from "./book-sort.js"
-import chapterToggle from "./chapter-toggle.js"
+import chapterContents from "./chapter-contents.js"
 import codeEditor from "./code-editor.js"
 import codeHighlighter from "./code-highlighter.js"
+import codeTextarea from "./code-textarea.js"
 import collapsible from "./collapsible.js"
 import confirmDialog from "./confirm-dialog"
 import customCheckbox from "./custom-checkbox.js"
@@ -62,9 +63,10 @@ const componentMapping = {
     "auto-suggest": autoSuggest,
     "back-to-top": backToTop,
     "book-sort": bookSort,
-    "chapter-toggle": chapterToggle,
+    "chapter-contents": chapterContents,
     "code-editor": codeEditor,
     "code-highlighter": codeHighlighter,
+    "code-textarea": codeTextarea,
     "collapsible": collapsible,
     "confirm-dialog": confirmDialog,
     "custom-checkbox": customCheckbox,
index 297d9c8ece8bcdae60befb118b59ffc2388165de..21cf37bb4438d745a3dbbf7225773cf8474a6c83 100644 (file)
@@ -2,7 +2,7 @@ import MarkdownIt from "markdown-it";
 import mdTasksLists from 'markdown-it-task-lists';
 import Clipboard from "../services/clipboard";
 import {debounce} from "../services/util";
-
+import {patchDomFromHtmlString} from "../services/vdom";
 import DrawIO from "../services/drawio";
 
 class MarkdownEditor {
@@ -127,18 +127,31 @@ class MarkdownEditor {
     updateAndRender() {
         const content = this.cm.getValue();
         this.input.value = content;
+
         const html = this.markdown.render(content);
         window.$events.emit('editor-html-change', html);
         window.$events.emit('editor-markdown-change', content);
 
         // Set body content
+        const target = this.getDisplayTarget();
         this.displayDoc.body.className = 'page-content';
-        this.displayDoc.body.innerHTML = html;
+        patchDomFromHtmlString(target, html);
 
         // Copy styles from page head and set custom styles for editor
         this.loadStylesIntoDisplay();
     }
 
+    getDisplayTarget() {
+        const body = this.displayDoc.body;
+
+        if (body.children.length === 0) {
+            const wrap = document.createElement('div');
+            this.displayDoc.body.append(wrap);
+        }
+
+        return body.children[0];
+    }
+
     loadStylesIntoDisplay() {
         if (this.displayStylesLoaded) return;
         this.displayDoc.documentElement.classList.add('markdown-editor-display');
index 278a765d5802e2af4feefd1fb1cb26aeaee9b805..12b8077cf7dccec37dc48e6f83a7c6aa1ce43c86 100644 (file)
@@ -49,7 +49,7 @@ export function slideUp(element, animTime = 400) {
     const currentPaddingTop = computedStyles.getPropertyValue('padding-top');
     const currentPaddingBottom = computedStyles.getPropertyValue('padding-bottom');
     const animStyles = {
-        height: [`${currentHeight}px`, '0px'],
+        maxHeight: [`${currentHeight}px`, '0px'],
         overflow: ['hidden', 'hidden'],
         paddingTop: [currentPaddingTop, '0px'],
         paddingBottom: [currentPaddingBottom, '0px'],
@@ -73,7 +73,7 @@ export function slideDown(element, animTime = 400) {
     const targetPaddingTop = computedStyles.getPropertyValue('padding-top');
     const targetPaddingBottom = computedStyles.getPropertyValue('padding-bottom');
     const animStyles = {
-        height: ['0px', `${targetHeight}px`],
+        maxHeight: ['0px', `${targetHeight}px`],
         overflow: ['hidden', 'hidden'],
         paddingTop: ['0px', targetPaddingTop],
         paddingBottom: ['0px', targetPaddingBottom],
@@ -82,6 +82,38 @@ export function slideDown(element, animTime = 400) {
     animateStyles(element, animStyles, animTime);
 }
 
+/**
+ * Transition the height of the given element between two states.
+ * Call with first state, and you'll receive a function in return.
+ * Call the returned function in the second state to animate between those two states.
+ * If animating to/from 0-height use the slide-up/slide down as easier alternatives.
+ * @param {Element} element - Element to animate
+ * @param {Number} animTime - Animation time in ms
+ * @returns {function} - Function to run in second state to trigger animation.
+ */
+export function transitionHeight(element, animTime = 400) {
+    const startHeight = element.getBoundingClientRect().height;
+    const initialComputedStyles = getComputedStyle(element);
+    const startPaddingTop = initialComputedStyles.getPropertyValue('padding-top');
+    const startPaddingBottom = initialComputedStyles.getPropertyValue('padding-bottom');
+
+    return () => {
+        cleanupExistingElementAnimation(element);
+        const targetHeight = element.getBoundingClientRect().height;
+        const computedStyles = getComputedStyle(element);
+        const targetPaddingTop = computedStyles.getPropertyValue('padding-top');
+        const targetPaddingBottom = computedStyles.getPropertyValue('padding-bottom');
+        const animStyles = {
+            height: [`${startHeight}px`, `${targetHeight}px`],
+            overflow: ['hidden', 'hidden'],
+            paddingTop: [startPaddingTop, targetPaddingTop],
+            paddingBottom: [startPaddingBottom, targetPaddingBottom],
+        };
+
+        animateStyles(element, animStyles, animTime);
+    };
+}
+
 /**
  * Animate the css styles of an element using FLIP animation techniques.
  * Styles must be an object where the keys are style properties, camelcase, and the values
diff --git a/resources/js/services/vdom.js b/resources/js/services/vdom.js
new file mode 100644 (file)
index 0000000..89a8090
--- /dev/null
@@ -0,0 +1,31 @@
+import {
+    init,
+    attributesModule,
+    toVNode
+} from "snabbdom";
+
+let patcher;
+
+/**
+ * @returns {Function}
+ */
+function getPatcher() {
+    if (patcher) return patcher;
+
+
+    patcher = init([
+        attributesModule,
+    ]);
+
+    return patcher;
+}
+
+/**
+ * @param {Element} domTarget
+ * @param {String} html
+ */
+export function patchDomFromHtmlString(domTarget, html) {
+    const contentDom = document.createElement('div');
+    contentDom.innerHTML = html;
+    getPatcher()(toVNode(domTarget), toVNode(contentDom));
+}
\ No newline at end of file
index ace74dd334e03c8a17bcfbf527ae3d178ac44295..0529f6b6cdd110f00335b3a5c2785df608e7fe71 100644 (file)
@@ -60,13 +60,7 @@ async function uploadImageFile(file, pageId) {
         throw new Error(`Not an image file`);
     }
 
-    let ext = 'png';
-    if (file.name) {
-        let fileNameMatches = file.name.match(/\.(.+)$/);
-        if (fileNameMatches.length > 1) ext = fileNameMatches[1];
-    }
-
-    const remoteFilename = "image-" + Date.now() + "." + ext;
+    const remoteFilename = file.name || `image-${Date.now()}.png`;
     const formData = new FormData();
     formData.append('file', file, remoteFilename);
     formData.append('uploaded_to', pageId);
index 82ab7d3c8eebad8327a842ef208c575e6451ded0..4123fb783a96cec3694d8366af5111a987820ed5 100644 (file)
@@ -86,7 +86,13 @@ function defineCodeBlockCustomElement(editor) {
         getContent() {
             const code = this.querySelector('code') || this.querySelector('pre');
             const tempEl = document.createElement('pre');
-            tempEl.innerHTML = code.innerHTML.replace().replace(/<br\s*[\/]?>/gi ,'\n').replace(/\ufeff/g, '');
+            tempEl.innerHTML = code.innerHTML.replace(/\ufeff/g, '');
+
+            const brs = tempEl.querySelectorAll('br');
+            for (const br of brs) {
+                br.replaceWith('\n');
+            }
+
             return tempEl.textContent;
         }
 
@@ -104,6 +110,7 @@ function defineCodeBlockCustomElement(editor) {
 
             const container = this.shadowRoot.querySelector('.CodeMirrorContainer');
             const renderCodeMirror = (Code) => {
+                console.log({content});
                 this.cm = Code.wysiwygView(container, content, this.getLanguage());
                 Code.updateLayout(this.cm);
                 setTimeout(() => {
@@ -159,6 +166,7 @@ function register(editor, url) {
             showPopup(editor, textContent, '', (newCode, newLang) => {
                 const pre = doc.createElement('pre');
                 const code = doc.createElement('code');
+                console.log(newCode);
                 code.classList.add(`language-${newLang}`);
                 code.innerText = newCode;
                 pre.append(code);
index 678fb1412681d1258bca3b9e7be053707ed8677f..1cda8b8295e4794b338b1468f8d7c05d81e22e8c 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'تم إنشاء كتاب',
     'book_create_notification'    => 'تم إنشاء الكتاب بنجاح',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'تم تحديث الكتاب',
     'book_update_notification'    => 'تم تحديث الكتاب بنجاح',
     'book_delete'                 => 'تم حذف الكتاب',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'تم إنشاء رف كتب',
     'bookshelf_create_notification'    => 'تم إنشاء الرف بنجاح',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'تم تحديث الرف',
     'bookshelf_update_notification'    => 'تم تحديث الرف بنجاح',
     'bookshelf_delete'                 => 'تم تحديث الرف',
index 766165961ba5ade08533813d733ae92c963e9a2c..a3b70612dede70d0bd85642d969936bd01c39e22 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'المجال الخاص بالبريد الإلكتروني لا يملك حق الوصول لهذا التطبيق',
     'register_success' => 'شكراً لإنشاء حسابكم! تم تسجيلكم ودخولكم للحساب الخاص بكم.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'استعادة كلمة المرور',
     'reset_password_send_instructions' => 'أدخل بريدك الإلكتروني بالأسفل وسيتم إرسال رسالة برابط لاستعادة كلمة المرور.',
index 37c43597bf62c60bf7f112095f4c96f229fa5ceb..6d34d3ee8b885ee579535a1c60b6742190da5604 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Previous',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'خيارات الفرز',
index dbb89bc8f7accbb3a2ec9cf365dc932eedb0a7e2..16ecb6ad90e9cde981e578d7cf7e63a27261c01c 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index f1a48913167a5ecb45f6dd7420ce41ee6361ba5b..52a6c78aa82587b43619c9efc17a4a2ea587c249 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'създадена книга',
     'book_create_notification'    => 'Книгата е създадена успешно',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'обновена книга',
     'book_update_notification'    => 'Книгата е обновена успешно',
     'book_delete'                 => 'изтрита книга',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'създаден рафт',
     'bookshelf_create_notification'    => 'Рафтът е създаден успешно',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'обновен рафт',
     'bookshelf_update_notification'    => 'Рафтът е обновен успешно',
     'bookshelf_delete'                 => 'изтрит рафт',
index 67397a9c5db4bacbe92e0b6569e2a6172c8a3dfd..97476e8be1652ac62f9304d6a592675ecd215238 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Този емейл домейн към момента няма достъп до приложението',
     'register_success' => 'Благодарим Ви за регистрацията! В момента сте регистриран и сте вписани в приложението.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Нулиране на паролата',
     'reset_password_send_instructions' => 'Въведете емейла си и ще ви бъде изпратен емейл с линк за нулиране на паролата.',
index 889483d01b6228715e001c32fc4258e9a6176fc5..0d070c84c3b2fe6515b5096442059aaded8da642 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Предишен',
     'filter_active' => 'Активен филтър:',
     'filter_clear' => 'Изчисти филтъра',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Опции за сортиране',
index a1faad7cd507aa9e6032212389eb7c8705c3721f..462e9623a8a8f4a98f2fbcfef7a0dc30a7c3c945 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Файловете на изображенията в страницата няма да бъдат дубликирани и оригиналните изображения ще запазят връзката си със страницата, на която са били качени първоначално.',
     'copy_consider_attachments' => 'Прикачените към страницата обекти няма да бъдат копирани.',
     'copy_consider_access' => 'Смяна на местоположението, собственика или привилегиите може да направи това съдържание достъпно за тези, които не са го виждали преди.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 996cd1dfcf5ee665a075a09b92e7c0a291eda47a..16fefbe63e44bd820aa6c0c2cd7ce94c7c109809 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'je kreirao/la knjigu',
     'book_create_notification'    => 'Book successfully created',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'je ažurirao/la knjigu',
     'book_update_notification'    => 'Book successfully updated',
     'book_delete'                 => 'je izbrisao/la knjigu',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'je ažurirao/la policu za knjige',
     'bookshelf_update_notification'    => 'Bookshelf successfully updated',
     'bookshelf_delete'                 => 'je izbrisao/la policu za knjige',
index 5b01b705e0077a8c1a7e041b935619763081be76..b9a72e2cfe6d15e038bbb8a827e52867e11e0cdb 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Ta e-mail domena nema pristup ovoj aplikaciji',
     'register_success' => 'Hvala na registraciji! Sada ste registrovani i prijavljeni.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Resetuj Lozinku',
     'reset_password_send_instructions' => 'Unesite vašu e-mail adresu ispod i na nju ćemo vam poslati e-mail sa linkom za promjenu lozinke.',
index cd844a02e98ba08756db4cf6643b2b33a4599f2a..0008cbcc8c700194adf340dff62184fb311774a4 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Prethodno',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Opcije sortiranja',
index afa5f39e927b5d35048333fb819b2e0aa991467b..c9cd0bb5dfcdd46ba9343312c46f6d4e52f77071 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index a2c8eb30c3c1fb6d7f7597398740e10cae3accd7..083f45656ad49f5f2bfae80a265d966cc787a9bd 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'ha creat el llibre',
     'book_create_notification'    => 'Book successfully created',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'ha actualitzat el llibre',
     'book_update_notification'    => 'Book successfully updated',
     'book_delete'                 => 'ha suprimit un llibre',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'ha actualitzat el prestatge',
     'bookshelf_update_notification'    => 'Bookshelf successfully updated',
     'bookshelf_delete'                 => 'ha suprimit un prestatge',
index ab45b0f992ff1277d4be29c58f9e360117cb172b..b95ae1e6dcdf62d9849d153987c3e4a8a778699f 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Aquest domini de correu electrònic no té accés a aquesta aplicació',
     'register_success' => 'Gràcies per registrar-vos! Ja us hi heu registrat i heu iniciat la sessió.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Restableix la contrasenya',
     'reset_password_send_instructions' => 'Introduïu la vostra adreça electrònica a continuació i us enviarem un correu electrònic amb un enllaç per a restablir la contrasenya.',
index 21817683fc22787af54c3918d06ee4da67e60023..7c8ec04a33896d92e4376ad83c4c4ef1d242542d 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Previous',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Opcions d\'ordenació',
index 1791658281569c9b32425184b35782945fc004c9..be5d33948c166e26498331c61507d0131895209c 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 09241df3e7b094cec71e6adddc96c0b75296389b..2de8532d46f2eaec7dda910c1a454da8a86c239d 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'vytvořil/a knihu',
     'book_create_notification'    => 'Kniha byla úspěšně vytvořena',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'aktualizoval/a knihu',
     'book_update_notification'    => 'Kniha byla úspěšně aktualizována',
     'book_delete'                 => 'odstranil/a knihu',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'vytvořil/a knihovnu',
     'bookshelf_create_notification'    => 'Knihovna byla úspěšně vytvořena',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'aktualizoval/a knihovnu',
     'bookshelf_update_notification'    => 'Knihovna byla úspěšně aktualizována',
     'bookshelf_delete'                 => 'odstranil/a knihovnu',
index e2f92863a23555034928d374815b713978722b53..00ed80cf86ffd049f7e4610bea8adad9e948d73a 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Registrace z této e-mailové domény nejsou povoleny',
     'register_success' => 'Děkujeme za registraci! Nyní jste zaregistrováni a přihlášeni.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Obnovit heslo',
     'reset_password_send_instructions' => 'Níže zadejte svou e-mailovou adresu a bude vám zaslán e-mail s odkazem na obnovení hesla.',
index 2a496f481ccddf215e4cb380ac5fdd8a9a1afbf5..bbf271fe4813f61ecf71ae1e19725de5b8f6d497 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Předchozí',
     'filter_active' => 'Aktivní filtr:',
     'filter_clear' => 'Zrušit filtr',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Možnosti řazení',
index ab0b103d6dea3987e70c51ffb4501527b77a590f..a7e42fd4f1d9358589b88d9313de52f39b65022f 100644 (file)
@@ -247,7 +247,7 @@ return [
     'pages_permissions_active' => 'Oprávnění stránky byla aktivována',
     'pages_initial_revision' => 'První vydání',
     'pages_initial_name' => 'Nová stránka',
-    'pages_editing_draft_notification' => 'Právě upravujete koncept, který byl uložen před :timeDiff.',
+    'pages_editing_draft_notification' => 'Právě upravujete koncept, který byl uložen :timeDiff.',
     'pages_draft_edited_notification' => 'Tato stránka se od té doby změnila. Je doporučeno aktuální koncept zahodit.',
     'pages_draft_page_changed_since_creation' => 'Tato stránka byla aktualizována od vytvoření tohoto konceptu. Doporučuje se zrušit tento koncept nebo se postarat o to, abyste si nepřepsali žádné již zadané změny.',
     'pages_draft_edit_active' => [
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Přílohy stránky nebudou zkopírovány.',
     'copy_consider_access' => 'Po změně umístění, vlastníka nebo oprávnění může dojít k tomu, že obsah může být přístupný těm, kteří přístup dříve něměli.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
diff --git a/resources/lang/cy/activities.php b/resources/lang/cy/activities.php
new file mode 100644 (file)
index 0000000..b1a643d
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Activity text strings.
+ * Is used for all the text within activity logs & notifications.
+ */
+return [
+
+    // Pages
+    'page_create'                 => 'tudalen wedi\'i chreu',
+    'page_create_notification'    => 'Tudalen wedi\'i chreu\'n llwyddiannus',
+    'page_update'                 => 'tudalen wedi\'i diweddaru',
+    'page_update_notification'    => 'Tudalen wedi\'i diweddaru\'n llwyddiannus',
+    'page_delete'                 => 'tudalen wedi\'i dileu',
+    'page_delete_notification'    => 'Cafodd y dudalen ei dileu yn llwyddiannus',
+    'page_restore'                => 'tudalen wedi\'i hadfer',
+    'page_restore_notification'   => 'Cafodd y dudalen ei hadfer yn llwyddiannus',
+    'page_move'                   => 'symwyd tudalen',
+
+    // Chapters
+    'chapter_create'              => 'pennod creu',
+    'chapter_create_notification' => 'Pennod wedi\'i chreu\'n llwyddiannus',
+    'chapter_update'              => 'pennod wedi diweddaru',
+    'chapter_update_notification' => 'Pennod wedi\'i diweddaru\'n llwyddiannus',
+    'chapter_delete'              => 'pennod wedi dileu',
+    'chapter_delete_notification' => 'Pennod wedi\'i dileu\'n llwyddiannus',
+    'chapter_move'                => 'pennod wedi symud',
+
+    // Books
+    'book_create'                 => 'llyfr wedi creu',
+    'book_create_notification'    => 'Llyfr wedi\'i creu\'n llwyddiannus',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
+    'book_update'                 => 'llyfr wedi diweddaru',
+    'book_update_notification'    => 'Llyfr wedi\'i diweddaru\'n llwyddiannus',
+    'book_delete'                 => 'llyfr wedi\'i dileu',
+    'book_delete_notification'    => 'Cafodd y llyfr ei dileu yn llwyddiannus',
+    'book_sort'                   => 'llyfr wedi\'i ddidoli',
+    'book_sort_notification'      => 'Ail-archebwyd y llyfr yn llwyddiannus',
+
+    // Bookshelves
+    'bookshelf_create'            => 'creu silff lyfrau',
+    'bookshelf_create_notification'    => 'Silff lyfrau wedi\'i chreu\'n llwyddiannus',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
+    'bookshelf_update'                 => 'silff lyfrau wedi\'i diweddaru',
+    'bookshelf_update_notification'    => 'Diweddarwyd y silff lyfrau yn llwyddiannus',
+    'bookshelf_delete'                 => 'silff lyfrau wedi\'i dileu',
+    'bookshelf_delete_notification'    => 'Silff lyfrau wedi\'i dileu\'n llwyddiannus',
+
+    // Favourites
+    'favourite_add_notification' => 'Mae ":name" wedi\'i ychwanegu at eich ffefrynnau',
+    'favourite_remove_notification' => 'Mae ":name" wedi\'i tynnu o\'ch ffefrynnau',
+
+    // MFA
+    'mfa_setup_method_notification' => 'Dull aml-ffactor wedi\'i ffurfweddu\'n llwyddiannus',
+    'mfa_remove_method_notification' => 'Llwyddwyd i ddileu dull aml-ffactor',
+
+    // Webhooks
+    'webhook_create' => 'webhook wedi creu',
+    'webhook_create_notification' => 'Webhook wedi\'i creu\'n llwyddiannus',
+    'webhook_update' => 'webhook wedi\'i diweddaru',
+    'webhook_update_notification' => 'Webhook wedi\'i diweddaru\'n llwyddiannus',
+    'webhook_delete' => 'webhook wedi\'i dileu',
+    'webhook_delete_notification' => 'Webhook wedi\'i dileu\'n llwyddiannus',
+
+    // Users
+    'user_update_notification' => 'Diweddarwyd y defnyddiwr yn llwyddiannus',
+    'user_delete_notification' => 'Tynnwyd y defnyddiwr yn llwyddiannus',
+
+    // Other
+    'commented_on'                => 'gwnaeth sylwadau ar',
+    'permissions_update'          => 'caniatadau wedi\'u diweddaru',
+];
diff --git a/resources/lang/cy/auth.php b/resources/lang/cy/auth.php
new file mode 100644 (file)
index 0000000..bb00857
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+/**
+ * Authentication Language Lines
+ * The following language lines are used during authentication for various
+ * messages that we need to display to the user.
+ */
+return [
+
+    'failed' => 'Nid yw\'r manylion hyn yn cyfateb i\'n cofnodion.',
+    'throttle' => 'Gormod o ymdrechion mewngofnodi. Rhowch gynnig arall arni o gwmpas :seconds eiliadau.',
+
+    // Login & Register
+    'sign_up' => 'Cofrestru',
+    'log_in' => 'Mewngofnodi',
+    'log_in_with' => 'Mewngofnodi efo :socialDriver',
+    'sign_up_with' => 'Cofrestru efo :socialDriver',
+    'logout' => 'Allgofnodi',
+
+    'name' => 'Enw',
+    'username' => 'Enw defnyddiwr',
+    'email' => 'Ebost',
+    'password' => 'Cyfrinair',
+    'password_confirm' => 'Cadarnhau cyfrinair',
+    'password_hint' => 'Rhaid bod o leiaf 8 nod',
+    'forgot_password' => 'Wedi anghofio cyfrinair?',
+    'remember_me' => 'Cofiwch fi',
+    'ldap_email_hint' => 'Rhowch e-bost i\'w ddefnyddio ar gyfer y cyfrif hwn.',
+    'create_account' => 'Creu cyfrif',
+    'already_have_account' => 'Oes gennych chi gyfrif yn barod?',
+    'dont_have_account' => 'Dim cyfrif?',
+    'social_login' => 'Mewngofnodi cymdeithasol',
+    'social_registration' => 'Cofrestru cymdeithasol',
+    'social_registration_text' => 'Cofrestru a mewngofnodi gan ddefnyddio dyfais arall.',
+
+    'register_thanks' => 'Diolch am cofrestru!',
+    'register_confirm' => 'Gwiriwch eich e-bost a chliciwch ar y botwm cadarnhau i gael mynediad i: appName.',
+    'registrations_disabled' => 'Mae cofrestriadau wedi\'u hanalluogi ar hyn o bryd',
+    'registration_email_domain_invalid' => 'Nid oes gan y parth e-bost hwnnw fynediad i\'r rhaglen hon',
+    'register_success' => 'Diolch am arwyddo! Rydych bellach wedi cofrestru ac wedi mewngofnodi.',
+
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
+    // Password Reset
+    'reset_password' => 'Ailosod cyfrinair',
+    'reset_password_send_instructions' => 'Rhowch eich e-bost isod ac anfonir e-bost atoch gyda dolen ailosod cyfrinair.',
+    'reset_password_send_button' => 'Anfon Dolen Ailosod',
+    '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! You should now be able to login using this email address.',
+    '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_login' => 'Password set, you should now be able to login using your set password to access :appName!',
+
+    // Multi-factor Authentication
+    'mfa_setup' => 'Setup Multi-Factor Authentication',
+    'mfa_setup_desc' => 'Setup multi-factor authentication as an extra layer of security for your user account.',
+    'mfa_setup_configured' => 'Already configured',
+    'mfa_setup_reconfigure' => 'Reconfigure',
+    'mfa_setup_remove_confirmation' => 'Are you sure you want to remove this multi-factor authentication method?',
+    'mfa_setup_action' => 'Setup',
+    'mfa_backup_codes_usage_limit_warning' => 'You have less than 5 backup codes remaining, Please generate and store a new set before you run out of codes to prevent being locked out of your account.',
+    'mfa_option_totp_title' => 'Mobile App',
+    'mfa_option_totp_desc' => 'To use multi-factor authentication you\'ll need a mobile application that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.',
+    'mfa_option_backup_codes_title' => 'Backup Codes',
+    'mfa_option_backup_codes_desc' => 'Securely store a set of one-time-use backup codes which you can enter to verify your identity.',
+    'mfa_gen_confirm_and_enable' => 'Confirm and Enable',
+    'mfa_gen_backup_codes_title' => 'Backup Codes Setup',
+    'mfa_gen_backup_codes_desc' => 'Store the below list of codes in a safe place. When accessing the system you\'ll be able to use one of the codes as a second authentication mechanism.',
+    'mfa_gen_backup_codes_download' => 'Download Codes',
+    'mfa_gen_backup_codes_usage_warning' => 'Each code can only be used once',
+    'mfa_gen_totp_title' => 'Mobile App Setup',
+    'mfa_gen_totp_desc' => 'To use multi-factor authentication you\'ll need a mobile application that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.',
+    'mfa_gen_totp_scan' => 'Scan the QR code below using your preferred authentication app to get started.',
+    'mfa_gen_totp_verify_setup' => 'Verify Setup',
+    'mfa_gen_totp_verify_setup_desc' => 'Verify that all is working by entering a code, generated within your authentication app, in the input box below:',
+    'mfa_gen_totp_provide_code_here' => 'Provide your app generated code here',
+    'mfa_verify_access' => 'Verify Access',
+    'mfa_verify_access_desc' => 'Your user account requires you to confirm your identity via an additional level of verification before you\'re granted access. Verify using one of your configured methods to continue.',
+    'mfa_verify_no_methods' => 'No Methods Configured',
+    'mfa_verify_no_methods_desc' => 'No multi-factor authentication methods could be found for your account. You\'ll need to set up at least one method before you gain access.',
+    'mfa_verify_use_totp' => 'Verify using a mobile app',
+    'mfa_verify_use_backup_codes' => 'Verify using a backup code',
+    'mfa_verify_backup_code' => 'Backup Code',
+    'mfa_verify_backup_code_desc' => 'Enter one of your remaining backup codes below:',
+    'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
+    'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
+    'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
+];
diff --git a/resources/lang/cy/common.php b/resources/lang/cy/common.php
new file mode 100644 (file)
index 0000000..703a70c
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Common elements found throughout many areas of BookStack.
+ */
+return [
+
+    // Buttons
+    'cancel' => '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',
+    'delete_confirm' => 'Confirm Deletion',
+    'search' => 'Search',
+    'search_clear' => 'Clear Search',
+    'reset' => 'Reset',
+    'remove' => 'Remove',
+    'add' => 'Add',
+    'configure' => 'Configure',
+    'fullscreen' => 'Fullscreen',
+    'favourite' => 'Favourite',
+    'unfavourite' => 'Unfavourite',
+    'next' => 'Next',
+    'previous' => 'Previous',
+    'filter_active' => 'Active Filter:',
+    'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
+
+    // Sort Options
+    'sort_options' => 'Sort Options',
+    'sort_direction_toggle' => 'Sort Direction Toggle',
+    'sort_ascending' => 'Sort Ascending',
+    'sort_descending' => 'Sort Descending',
+    'sort_name' => 'Name',
+    'sort_default' => 'Default',
+    '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',
+    'skip_to_main_content' => 'Skip to main content',
+    'toggle_details' => 'Toggle Details',
+    'toggle_thumbnails' => 'Toggle Thumbnails',
+    'details' => 'Details',
+    'grid_view' => 'Grid View',
+    'list_view' => 'List View',
+    'default' => 'Default',
+    'breadcrumb' => 'Breadcrumb',
+    'status' => 'Status',
+    'status_active' => 'Active',
+    'status_inactive' => 'Inactive',
+    'never' => 'Never',
+    'none' => 'None',
+
+    // Header
+    'header_menu_expand' => 'Expand Header Menu',
+    '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_info_label' => 'Tab: Show Secondary Information',
+    'tab_content' => 'Content',
+    'tab_content_label' => 'Tab: Show Primary 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',
+
+    // Footer Link Options
+    // Not directly used but available for convenience to users.
+    'privacy_policy' => 'Privacy Policy',
+    'terms_of_service' => 'Terms of Service',
+];
diff --git a/resources/lang/cy/components.php b/resources/lang/cy/components.php
new file mode 100644 (file)
index 0000000..48a0a32
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Text used in custom JavaScript driven components.
+ */
+return [
+
+    // Image Manager
+    'image_select' => '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_text' => 'Are you sure 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_session_history' => 'Session History',
+    'code_save' => 'Save Code',
+];
diff --git a/resources/lang/cy/editor.php b/resources/lang/cy/editor.php
new file mode 100644 (file)
index 0000000..8271202
--- /dev/null
@@ -0,0 +1,171 @@
+<?php
+/**
+ * Page Editor Lines
+ * Contains text strings used within the user interface of the
+ * WYSIWYG page editor. Some Markdown editor strings may still
+ * exist in the 'entities' file instead since this was added later.
+ */
+return [
+    // General editor terms
+    'general' => 'General',
+    'advanced' => 'Advanced',
+    'none' => 'None',
+    'cancel' => 'Cancel',
+    'save' => 'Save',
+    'close' => 'Close',
+    'undo' => 'Undo',
+    'redo' => 'Redo',
+    'left' => 'Left',
+    'center' => 'Center',
+    'right' => 'Right',
+    'top' => 'Top',
+    'middle' => 'Middle',
+    'bottom' => 'Bottom',
+    'width' => 'Width',
+    'height' => 'Height',
+    'More' => 'More',
+    'select' => 'Select...',
+
+    // Toolbar
+    'formats' => 'Formats',
+    'header_large' => 'Large Header',
+    'header_medium' => 'Medium Header',
+    'header_small' => 'Small Header',
+    'header_tiny' => 'Tiny Header',
+    'paragraph' => 'Paragraph',
+    'blockquote' => 'Blockquote',
+    'inline_code' => 'Inline code',
+    'callouts' => 'Callouts',
+    'callout_information' => 'Information',
+    'callout_success' => 'Success',
+    'callout_warning' => 'Warning',
+    'callout_danger' => 'Danger',
+    'bold' => 'Bold',
+    'italic' => 'Italic',
+    'underline' => 'Underline',
+    'strikethrough' => 'Strikethrough',
+    'superscript' => 'Superscript',
+    'subscript' => 'Subscript',
+    'text_color' => 'Text color',
+    'custom_color' => 'Custom color',
+    'remove_color' => 'Remove color',
+    'background_color' => 'Background color',
+    'align_left' => 'Align left',
+    'align_center' => 'Align center',
+    'align_right' => 'Align right',
+    'align_justify' => 'Justify',
+    'list_bullet' => 'Bullet list',
+    'list_numbered' => 'Numbered list',
+    'list_task' => 'Task list',
+    'indent_increase' => 'Increase indent',
+    'indent_decrease' => 'Decrease indent',
+    'table' => 'Table',
+    'insert_image' => 'Insert image',
+    'insert_image_title' => 'Insert/Edit Image',
+    'insert_link' => 'Insert/edit link',
+    'insert_link_title' => 'Insert/Edit Link',
+    'insert_horizontal_line' => 'Insert horizontal line',
+    'insert_code_block' => 'Insert code block',
+    'insert_drawing' => 'Insert/edit drawing',
+    'drawing_manager' => 'Drawing manager',
+    'insert_media' => 'Insert/edit media',
+    'insert_media_title' => 'Insert/Edit Media',
+    'clear_formatting' => 'Clear formatting',
+    'source_code' => 'Source code',
+    'source_code_title' => 'Source Code',
+    'fullscreen' => 'Fullscreen',
+    'image_options' => 'Image options',
+
+    // Tables
+    'table_properties' => 'Table properties',
+    'table_properties_title' => 'Table Properties',
+    'delete_table' => 'Delete table',
+    'insert_row_before' => 'Insert row before',
+    'insert_row_after' => 'Insert row after',
+    'delete_row' => 'Delete row',
+    'insert_column_before' => 'Insert column before',
+    'insert_column_after' => 'Insert column after',
+    'delete_column' => 'Delete column',
+    'table_cell' => 'Cell',
+    'table_row' => 'Row',
+    'table_column' => 'Column',
+    'cell_properties' => 'Cell properties',
+    'cell_properties_title' => 'Cell Properties',
+    'cell_type' => 'Cell type',
+    'cell_type_cell' => 'Cell',
+    'cell_scope' => 'Scope',
+    'cell_type_header' => 'Header cell',
+    'merge_cells' => 'Merge cells',
+    'split_cell' => 'Split cell',
+    'table_row_group' => 'Row Group',
+    'table_column_group' => 'Column Group',
+    'horizontal_align' => 'Horizontal align',
+    'vertical_align' => 'Vertical align',
+    'border_width' => 'Border width',
+    'border_style' => 'Border style',
+    'border_color' => 'Border color',
+    'row_properties' => 'Row properties',
+    'row_properties_title' => 'Row Properties',
+    'cut_row' => 'Cut row',
+    'copy_row' => 'Copy row',
+    'paste_row_before' => 'Paste row before',
+    'paste_row_after' => 'Paste row after',
+    'row_type' => 'Row type',
+    'row_type_header' => 'Header',
+    'row_type_body' => 'Body',
+    'row_type_footer' => 'Footer',
+    'alignment' => 'Alignment',
+    'cut_column' => 'Cut column',
+    'copy_column' => 'Copy column',
+    'paste_column_before' => 'Paste column before',
+    'paste_column_after' => 'Paste column after',
+    'cell_padding' => 'Cell padding',
+    'cell_spacing' => 'Cell spacing',
+    'caption' => 'Caption',
+    'show_caption' => 'Show caption',
+    'constrain' => 'Constrain proportions',
+    'cell_border_solid' => 'Solid',
+    'cell_border_dotted' => 'Dotted',
+    'cell_border_dashed' => 'Dashed',
+    'cell_border_double' => 'Double',
+    'cell_border_groove' => 'Groove',
+    'cell_border_ridge' => 'Ridge',
+    'cell_border_inset' => 'Inset',
+    'cell_border_outset' => 'Outset',
+    'cell_border_none' => 'None',
+    'cell_border_hidden' => 'Hidden',
+
+    // Images, links, details/summary & embed
+    'source' => 'Source',
+    'alt_desc' => 'Alternative description',
+    'embed' => 'Embed',
+    'paste_embed' => 'Paste your embed code below:',
+    'url' => 'URL',
+    'text_to_display' => 'Text to display',
+    'title' => 'Title',
+    'open_link' => 'Open link in...',
+    'open_link_current' => 'Current window',
+    'open_link_new' => 'New window',
+    'insert_collapsible' => 'Insert collapsible block',
+    'collapsible_unwrap' => 'Unwrap',
+    'edit_label' => 'Edit label',
+    'toggle_open_closed' => 'Toggle open/closed',
+    'collapsible_edit' => 'Edit collapsible block',
+    'toggle_label' => 'Toggle label',
+
+    // About view
+    'about' => 'About the editor',
+    'about_title' => 'About the WYSIWYG Editor',
+    'editor_license' => 'Editor License & Copyright',
+    'editor_tiny_license' => 'This editor is built using :tinyLink which is provided under an LGPL v2.1 license.',
+    'editor_tiny_license_link' => 'The copyright and license details of TinyMCE can be found here.',
+    'save_continue' => 'Save Page & Continue',
+    'callouts_cycle' => '(Keep pressing to toggle through types)',
+    'link_selector' => 'Link to content',
+    'shortcuts' => 'Shortcuts',
+    'shortcut' => 'Shortcut',
+    'shortcuts_intro' => 'The following shortcuts are available in the editor:',
+    'windows_linux' => '(Windows/Linux)',
+    'mac' => '(Mac)',
+    'description' => 'Description',
+];
diff --git a/resources/lang/cy/entities.php b/resources/lang/cy/entities.php
new file mode 100644 (file)
index 0000000..27d6748
--- /dev/null
@@ -0,0 +1,370 @@
+<?php
+/**
+ * Text used for 'Entities' (Document Structure Elements) such as
+ * Books, Shelves, Chapters & Pages
+ */
+return [
+
+    // Shared
+    'recently_created' => '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',
+    'meta_owned_name' => 'Owned by :user',
+    'entity_select' => 'Entity Select',
+    'images' => 'Images',
+    'my_recent_drafts' => 'My Recent Drafts',
+    'my_recently_viewed' => 'My Recently Viewed',
+    'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+    'my_favourites' => 'My Favourites',
+    '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',
+    'export_md' => 'Markdown 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',
+    'permissions_owner' => 'Owner',
+
+    // 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_advanced' => 'Advanced Search',
+    'search_terms' => 'Search Terms',
+    '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_owned_by_me' => 'Owned 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_permissions_cascade_warning' => 'Permissions on bookshelves do not automatically cascade to contained books. This is because a book can exist on multiple shelves. Permissions can however be copied down to child books using the option found below.',
+    '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',
+    'books_copy' => 'Copy Book',
+    'books_copy_success' => 'Book successfully copied',
+
+    // 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 that exist within this chapter will also be deleted.',
+    '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_copy' => 'Copy Chapter',
+    'chapters_copy_success' => 'Chapter successfully copied',
+    '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_switch_to_markdown' => 'Switch to Markdown Editor',
+    'pages_edit_switch_to_markdown_clean' => '(Clean Content)',
+    'pages_edit_switch_to_markdown_stable' => '(Stable Content)',
+    'pages_edit_switch_to_wysiwyg' => 'Switch to WYSIWYG Editor',
+    '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_editor_switch_title' => 'Switch Editor',
+    'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?',
+    'pages_editor_switch_consider_following' => 'Consider the following when changing editors:',
+    'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.',
+    'pages_editor_switch_consideration_b' => 'This can potentially lead to a loss of detail and syntax in certain circumstances.',
+    'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.',
+    '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_revision_restored_from' => 'Restored from #:id; :summary',
+    '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_editor' => 'Editor Type',
+    '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_page_changed_since_creation' => 'This page has been updated since this draft was created. It is recommended that you discard this draft or take care not to overwrite any page changes.',
+    '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',
+    'tags_usages' => 'Total tag usages',
+    'tags_assigned_pages' => 'Assigned to Pages',
+    'tags_assigned_chapters' => 'Assigned to Chapters',
+    'tags_assigned_books' => 'Assigned to Books',
+    'tags_assigned_shelves' => 'Assigned to Shelves',
+    'tags_x_unique_values' => ':count unique values',
+    'tags_all_values' => 'All values',
+    'tags_view_tags' => 'View Tags',
+    'tags_view_existing_tags' => 'View existing tags',
+    'tags_list_empty_hint' => 'Tags can be assigned via the page editor sidebar or while editing the details of a book, chapter or shelf.',
+    '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' => 'Are you sure 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_insert_link' => 'Add Attachment Link to Page',
+    '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.',
+
+    // Copy view
+    'copy_consider' => 'Please consider the below when copying content.',
+    'copy_consider_permissions' => 'Custom permission settings will not be copied.',
+    'copy_consider_owner' => 'You will become the owner of all copied content.',
+    'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
+    'copy_consider_attachments' => 'Page attachments will not be copied.',
+    'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
+];
diff --git a/resources/lang/cy/errors.php b/resources/lang/cy/errors.php
new file mode 100644 (file)
index 0000000..d540bae
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+/**
+ * Text shown in error messaging.
+ */
+return [
+
+    // Permissions
+    'permission' => 'Nid oes gennych ganiatâd i gael mynediad i\'r dudalen y gofynnwyd amdani.',
+    'permissionJson' => 'Nid oes gennych ganiatâd i gyflawni\'r weithred y gofynnwyd amdani.',
+
+    // Auth
+    'error_user_exists_different_creds' => 'Mae defnyddiwr gyda\'r e-bost :email eisoes yn bodoli ond gyda nodweddion gwahanol.',
+    'email_already_confirmed' => 'E-bost eisoes wedi\'i gadarnhau, Ceisiwch fewngofnodi.',
+    'email_confirmation_invalid' => 'Nid yw\'r tocyn cadarnhau hwn yn ddilys neu mae eisoes wedi\'i ddefnyddio. Ceisiwch gofrestru eto.',
+    'email_confirmation_expired' => 'Mae\'r tocyn cadarnhad wedi dod i ben, Mae e-bost cadarnhau newydd wedi\'i anfon.',
+    'email_confirmation_awaiting' => 'Mae angen cadarnhau cyfeiriad e-bost y cyfrif a ddefnyddir',
+    'ldap_fail_anonymous' => 'Methodd mynediad LDAP gan ddefnyddio rhwymiad dienw',
+    'ldap_fail_authed' => 'Methodd mynediad LDAP gan ddefnyddio\'r manylion dn a chyfrinair a roddwyd',
+    'ldap_extension_not_installed' => 'Estyniad PHP LDAP heb ei osod',
+    'ldap_cannot_connect' => 'Methu cysylltu i weinydd ldap, cysylltiad cychwynnol wedi methu',
+    'saml_already_logged_in' => 'Wedi mewngofnodi yn barod',
+    'saml_user_not_registered' => 'Nid yw\'r defnyddiwr :name wedi\'i gofrestru ac mae cofrestriad awtomatig wedi\'i analluogi',
+    'saml_no_email_address' => 'Methu dod o hyd i gyfeiriad e-bost, ar gyfer y defnyddiwr hwn, yn y data a ddarparwyd gan y system ddilysu allanol',
+    'saml_invalid_response_id' => 'Nid yw\'r cais o\'r system ddilysu allanol yn cael ei gydnabod gan broses a ddechreuwyd gan y cais hwn. Gallai llywio yn ôl ar ôl mewngofnodi achosi\'r broblem hon.',
+    'saml_fail_authed' => 'Wedi methu mewngofnodi gan ddefnyddio :system, ni roddodd y system awdurdodiad llwyddiannus',
+    'oidc_already_logged_in' => 'Wedi mewngofnodi yn barod',
+    'oidc_user_not_registered' => 'Nid yw\'r defnyddiwr :name wedi\'i gofrestru ac mae cofrestriad awtomatig wedi\'i analluogi',
+    'oidc_no_email_address' => 'Methu dod o hyd i gyfeiriad e-bost, ar gyfer y defnyddiwr hwn, yn y data a ddarparwyd gan y system ddilysu allanol',
+    'oidc_fail_authed' => 'Wedi methu mewngofnodi gan ddefnyddio :system, ni roddodd y system awdurdodiad llwyddiannus',
+    'social_no_action_defined' => 'Dim gweithred wedi\'i diffinio',
+    'social_login_bad_response' => "Gwall a dderbyniwyd yn ystod mewngofnodi :socialAccount:\n:error",
+    'social_account_in_use' => 'Mae\'r cyfrif :socialAccount hwn eisoes yn cael ei ddefnyddio, Ceisiwch fewngofnodi trwy\'r opsiwn :socialAccount.',
+    'social_account_email_in_use' => 'Mae\'r e-bost :email eisoes yn cael ei ddefnyddio. Os oes gennych gyfrif yn barod gallwch gysylltu eich cyfrif :socialAccount o osodiadau eich proffil.',
+    'social_account_existing' => 'Mae\'r :socialAccount hwn eisoes ynghlwm wrth eich proffil.',
+    'social_account_already_used_existing' => 'Mae\'r cyfrif :socialAccount hwn eisoes yn cael ei ddefnyddio gan ddefnyddiwr arall.',
+    'social_account_not_used' => 'Nid yw\'r cyfrif :socialAccount hwn yn gysylltiedig ag unrhyw ddefnyddwyr. Atodwch ef yn eich gosodiadau proffil. ',
+    'social_account_register_instructions' => 'Os nad oes gennych gyfrif eto, gallwch gofrestru cyfrif gan ddefnyddio\'r opsiwn :socialAccount.',
+    'social_driver_not_found' => 'Gyrrwr cymdeithasol heb ei ganfod',
+    'social_driver_not_configured' => 'Nid yw eich gosodiadau cymdeithasol :socialAccount wedi\'u ffurfweddu\'n gywir.',
+    'invite_token_expired' => 'Mae\'r ddolen wahoddiad hon wedi dod i ben. Yn lle hynny, gallwch chi geisio ailosod cyfrinair eich cyfrif.',
+
+    // System
+    'path_not_writable' => 'Nid oedd modd uwchlwytho llwybr ffeil :filePath. Sicrhewch ei fod yn ysgrifenadwy i\'r gweinydd.',
+    'cannot_get_image_from_url' => 'Methu cael delwedd o :url',
+    'cannot_create_thumbs' => 'Ni all y gweinydd greu mân-luniau. Gwiriwch fod gennych yr estyniad GD PHP wedi\'i osod.',
+    'server_upload_limit' => 'Nid yw\'r gweinydd yn caniatáu uwchlwythiadau o\'r maint hwn. Rhowch gynnig ar faint ffeil llai.',
+    'uploaded'  => 'Nid yw\'r gweinydd yn caniatáu uwchlwythiadau o\'r maint hwn. Rhowch gynnig ar faint ffeil llai.',
+    'image_upload_error' => 'Bu gwall wrth uwchlwytho\'r ddelwedd',
+    'image_upload_type_error' => 'Mae\'r math o ddelwedd sy\'n cael ei huwchlwytho yn annilys',
+    'file_upload_timeout' => 'Mae\'r amser uwchlwytho ffeil wedi dod i ben.',
+
+    // Attachments
+    'attachment_not_found' => 'Ni chanfuwyd yr atodiad',
+
+    // Pages
+    'page_draft_autosave_fail' => 'Wedi methu cadw\'r drafft. Sicrhewch fod gennych gysylltiad rhyngrwyd cyn cadw\'r dudalen hon',
+    'page_custom_home_deletion' => 'Methu dileu tudalen tra ei bod wedi\'i gosod fel hafan',
+
+    // Entities
+    'entity_not_found' => 'Endid heb ei ganfod',
+    'bookshelf_not_found' => 'Heb ddod o hyd i\'r silff lyfrau',
+    'book_not_found' => 'Ni chanfuwyd y llyfr',
+    'page_not_found' => 'Heb ganfod y dudalen',
+    'chapter_not_found' => 'Pennod heb ei chanfod',
+    'selected_book_not_found' => 'Ni ddaethpwyd o hyd i\'r llyfr a ddewiswyd',
+    'selected_book_chapter_not_found' => 'Ni ddaethpwyd o hyd i\'r Llyfr neu\'r Bennod a ddewiswyd',
+    'guests_cannot_save_drafts' => 'Ni all gwesteion arbed drafftiau',
+
+    // Users
+    'users_cannot_delete_only_admin' => 'Ni allwch ddileu\'r unig weinyddwr',
+    'users_cannot_delete_guest' => 'Ni allwch ddileu\'r defnyddiwr gwadd',
+
+    // Roles
+    'role_cannot_be_edited' => 'Nid oes modd golygu\'r rôl hon',
+    'role_system_cannot_be_deleted' => 'Rôl system yw\'r rôl hon ac ni ellir ei dileu',
+    'role_registration_default_cannot_delete' => 'Ni ellir dileu\'r rôl hon tra ei bod wedi\'i gosod fel y rôl gofrestru ddiofyn',
+    'role_cannot_remove_only_admin' => 'Y defnyddiwr hwn yw\'r unig ddefnyddiwr sydd wedi\'i neilltuo i rôl y gweinyddwr. Neilltuo rôl y gweinyddwr i ddefnyddiwr arall cyn ceisio ei dynnu yma.',
+
+    // Comments
+    'comment_list' => 'Digwyddodd gwall wrth nôl y sylwadau.',
+    'cannot_add_comment_to_draft' => 'Ni allwch ychwanegu sylwadau at ddrafft.',
+    'comment_add' => 'Digwyddodd gwall wrth ychwanegu / diweddaru\'r sylw.',
+    'comment_delete' => 'Digwyddodd gwall wrth dileu\'r sylwad.',
+    'empty_comment' => 'Methu ychwanegu sylw gwag.',
+
+    // Error pages
+    '404_page_not_found' => 'Heb ganfod y dudalen',
+    'sorry_page_not_found' => 'Mae\'n ddrwg gennym, nid oedd modd dod o hyd i\'r dudalen roeddech yn chwilio amdani.',
+    'sorry_page_not_found_permission_warning' => 'Os oeddech yn disgwyl i\'r dudalen hon fodoli, efallai na fyddai gennych ganiatâd i\'w gweld.',
+    'image_not_found' => 'Heb ganfod y delwedd',
+    'image_not_found_subtitle' => 'Mae\'n ddrwg gennym, ni fu modd dod o hyd i\'r ffeil delwedd roeddech yn chwilio amdani.',
+    'image_not_found_details' => 'Os oeddech chi\'n disgwyl i\'r ddelwedd hon fodoli efallai ei bod wedi\'i dileu.',
+    'return_home' => 'Dychwelyd i gartref',
+    'error_occurred' => 'Digwyddodd Gwall',
+    'app_down' => 'Mae :appName i lawr ar hyn o bryd',
+    'back_soon' => 'Bydd yn ôl i fyny yn fuan.',
+
+    // API errors
+    'api_no_authorization_found' => 'Ni chanfuwyd tocyn awdurdodi ar y cais',
+    'api_bad_authorization_format' => 'Canfuwyd tocyn awdurdodi ar y cais ond roedd yn ymddangos bod y fformat yn anghywir',
+    'api_user_token_not_found' => 'Ni chanfuwyd tocyn API cyfatebol ar gyfer y tocyn awdurdodi a ddarparwyd',
+    'api_incorrect_token_secret' => 'Mae\'r gyfrinach a ddarparwyd ar gyfer y tocyn API defnyddiedig a roddwyd yn anghywir',
+    'api_user_no_api_permission' => 'Nid oes gan berchennog y tocyn API a ddefnyddiwyd ganiatâd i wneud galwadau API',
+    'api_user_token_expired' => 'Mae\'r tocyn awdurdodi a ddefnyddiwyd wedi dod i ben',
+
+    // Settings & Maintenance
+    'maintenance_test_email_failure' => 'Gwall a daflwyd wrth anfon e-bost prawf:',
+
+];
diff --git a/resources/lang/cy/pagination.php b/resources/lang/cy/pagination.php
new file mode 100644 (file)
index 0000000..85bd12f
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Pagination Language Lines
+ * The following language lines are used by the paginator library to build
+ * the simple pagination links.
+ */
+return [
+
+    'previous' => '&laquo; Previous',
+    'next'     => 'Next &raquo;',
+
+];
diff --git a/resources/lang/cy/passwords.php b/resources/lang/cy/passwords.php
new file mode 100644 (file)
index 0000000..b408f3c
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Password Reminder Language Lines
+ * The following language lines are the default lines which match reasons
+ * that are given by the password broker for a password update attempt has failed.
+ */
+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' => '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/cy/settings.php b/resources/lang/cy/settings.php
new file mode 100644 (file)
index 0000000..3bfe70b
--- /dev/null
@@ -0,0 +1,309 @@
+<?php
+/**
+ * Settings text strings
+ * Contains all text strings used in the general settings sections of BookStack
+ * including users and roles.
+ */
+return [
+
+    // Common Messages
+    'settings' => 'Settings',
+    'settings_save' => 'Save Settings',
+    'settings_save_success' => 'Settings saved',
+    'system_version' => 'System Version',
+    'categories' => 'Categories',
+
+    // 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_default_editor' => 'Default Page Editor',
+    'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.',
+    'app_custom_html' => 'Custom HTML Head Content',
+    'app_custom_html_desc' => 'Any content added here will be inserted into the bottom of the <head> 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. <br>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_footer_links' => 'Footer Links',
+    'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
+    'app_footer_links_label' => 'Link Label',
+    'app_footer_links_url' => 'Link URL',
+    'app_footer_links_add' => 'Add Footer Link',
+    'app_disable_comments' => 'Disable Comments',
+    'app_disable_comments_toggle' => 'Disable comments',
+    'app_disable_comments_desc' => 'Disables comments across all pages in the application. <br> 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. <br> 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_delete_images_only_in_revisions' => 'Also delete images that only exist in old page 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_recycle_bin_desc' => 'Deleted shelves, books, chapters & pages are sent to the recycle bin so they can be restored or permanently deleted. Older items in the recycle bin may be automatically removed after a while depending on system configuration.',
+    'maint_recycle_bin_open' => 'Open Recycle Bin',
+
+    // Recycle Bin
+    'recycle_bin' => 'Recycle Bin',
+    'recycle_bin_desc' => 'Here you can restore items that have been deleted or choose to permanently remove them from the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
+    'recycle_bin_deleted_item' => 'Deleted Item',
+    'recycle_bin_deleted_parent' => 'Parent',
+    'recycle_bin_deleted_by' => 'Deleted By',
+    'recycle_bin_deleted_at' => 'Deletion Time',
+    'recycle_bin_permanently_delete' => 'Permanently Delete',
+    'recycle_bin_restore' => 'Restore',
+    'recycle_bin_contents_empty' => 'The recycle bin is currently empty',
+    'recycle_bin_empty' => 'Empty Recycle Bin',
+    'recycle_bin_empty_confirm' => 'This will permanently destroy all items in the recycle bin including content contained within each item. Are you sure you want to empty the recycle bin?',
+    'recycle_bin_destroy_confirm' => 'This action will permanently delete this item, along with any child elements listed below, from the system and you will not be able to restore this content. Are you sure you want to permanently delete this item?',
+    'recycle_bin_destroy_list' => 'Items to be Destroyed',
+    'recycle_bin_restore_list' => 'Items to be Restored',
+    'recycle_bin_restore_confirm' => 'This action will restore the deleted item, including any child elements, to their original location. If the original location has since been deleted, and is now in the recycle bin, the parent item will also need to be restored.',
+    'recycle_bin_restore_deleted_parent' => 'The parent of this item has also been deleted. These will remain deleted until that parent is also restored.',
+    'recycle_bin_restore_parent' => 'Restore Parent',
+    'recycle_bin_destroy_notification' => 'Deleted :count total items from the recycle bin.',
+    'recycle_bin_restore_notification' => 'Restored :count total items from the recycle bin.',
+
+    // Audit Log
+    'audit' => 'Audit Log',
+    'audit_desc' => 'This audit log displays a list of activities tracked in the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
+    'audit_event_filter' => 'Event Filter',
+    'audit_event_filter_no_filter' => 'No Filter',
+    'audit_deleted_item' => 'Deleted Item',
+    'audit_deleted_item_name' => 'Name: :name',
+    'audit_table_user' => 'User',
+    'audit_table_event' => 'Event',
+    'audit_table_related' => 'Related Item or Detail',
+    'audit_table_ip' => 'IP Address',
+    'audit_table_date' => 'Activity Date',
+    'audit_date_from' => 'Date Range From',
+    'audit_date_to' => 'Date Range To',
+
+    // 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_mfa_enforced' => 'Requires Multi-Factor Authentication',
+    '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_export_content' => 'Export content',
+    'role_editor_change' => 'Change page editor',
+    'role_asset' => 'Asset Permissions',
+    'roles_system_warning' => 'Be aware that access to any of the above three permissions can allow a user to alter their own privileges or the privileges of others in the system. Only assign roles with these permissions to trusted users.',
+    '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_latest_activity' => 'Latest Activity',
+    '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 8 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_migrate_ownership' => 'Migrate Ownership',
+    'users_migrate_ownership_desc' => 'Select a user here if you want another user to become the owner of all items currently owned by this user.',
+    'users_none_selected' => 'No user selected',
+    'users_edit' => 'Edit User',
+    'users_edit_profile' => 'Edit Profile',
+    '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',
+    'users_mfa' => 'Multi-Factor Authentication',
+    'users_mfa_desc' => 'Setup multi-factor authentication as an extra layer of security for your user account.',
+    'users_mfa_x_methods' => ':count method configured|:count methods configured',
+    'users_mfa_configure' => 'Configure Methods',
+
+    // 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',
+
+    // Webhooks
+    'webhooks' => 'Webhooks',
+    'webhooks_create' => 'Create New Webhook',
+    'webhooks_none_created' => 'No webhooks have yet been created.',
+    'webhooks_edit' => 'Edit Webhook',
+    'webhooks_save' => 'Save Webhook',
+    'webhooks_details' => 'Webhook Details',
+    'webhooks_details_desc' => 'Provide a user friendly name and a POST endpoint as a location for the webhook data to be sent to.',
+    'webhooks_events' => 'Webhook Events',
+    'webhooks_events_desc' => 'Select all the events that should trigger this webhook to be called.',
+    'webhooks_events_warning' => 'Keep in mind that these events will be triggered for all selected events, even if custom permissions are applied. Ensure that use of this webhook won\'t expose confidential content.',
+    'webhooks_events_all' => 'All system events',
+    'webhooks_name' => 'Webhook Name',
+    'webhooks_timeout' => 'Webhook Request Timeout (Seconds)',
+    'webhooks_endpoint' => 'Webhook Endpoint',
+    'webhooks_active' => 'Webhook Active',
+    'webhook_events_table_header' => 'Events',
+    'webhooks_delete' => 'Delete Webhook',
+    'webhooks_delete_warning' => 'This will fully delete this webhook, with the name \':webhookName\', from the system.',
+    'webhooks_delete_confirm' => 'Are you sure you want to delete this webhook?',
+    'webhooks_format_example' => 'Webhook Format Example',
+    'webhooks_format_example_desc' => 'Webhook data is sent as a POST request to the configured endpoint as JSON following the format below. The "related_item" and "url" properties are optional and will depend on the type of event triggered.',
+    'webhooks_status' => 'Webhook Status',
+    'webhooks_last_called' => 'Last Called:',
+    'webhooks_last_errored' => 'Last Errored:',
+    'webhooks_last_error_message' => 'Last Error Message:',
+
+
+    //! 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' => 'العربية',
+        'bg' => 'Bǎlgarski',
+        'bs' => 'Bosanski',
+        'ca' => 'Català',
+        'cs' => 'Česky',
+        'da' => 'Dansk',
+        'de' => 'Deutsch (Sie)',
+        'de_informal' => 'Deutsch (Du)',
+        'es' => 'Español',
+        'es_AR' => 'Español Argentina',
+        'et' => 'Eesti keel',
+        'eu' => 'Euskara',
+        'fa' => 'فارسی',
+        'fr' => 'Français',
+        'he' => 'עברית',
+        'hr' => 'Hrvatski',
+        'hu' => 'Magyar',
+        'id' => 'Bahasa Indonesia',
+        'it' => 'Italian',
+        'ja' => '日本語',
+        'ko' => '한국어',
+        'lt' => 'Lietuvių Kalba',
+        'lv' => 'Latviešu Valoda',
+        'nl' => 'Nederlands',
+        'nb' => 'Norsk (Bokmål)',
+        'pl' => 'Polski',
+        'pt' => 'Português',
+        '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/cy/validation.php b/resources/lang/cy/validation.php
new file mode 100644 (file)
index 0000000..87efe28
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Validation Lines
+ * The following language lines contain the default error messages used by
+ * the validator class. Some of these rules have multiple versions such
+ * as the size rules. Feel free to tweak each of these messages here.
+ */
+return [
+
+    // Standard laravel validation lines
+    'accepted'             => 'Rhaid derbyn y :attribute.',
+    'active_url'           => 'Nid ywr :attribute yn URL dilys.',
+    'after'                => 'Rhaid i\'r :attribute bod yn dyddiad ar ol :date.',
+    'alpha'                => 'Rhaid ir :attribute cynnwys llythrennau yn unig.',
+    'alpha_dash'           => 'Dim ond llythrennau, rhifau, llinellau toriad a thanlinellau y gall y :attribute gynnwys.',
+    'alpha_num'            => 'Rhaid ir :attribute cynnwys llythrennau a rhifau yn unig.',
+    'array'                => 'Rhaid i :attribute fod yn array.',
+    'backup_codes'         => 'Nid yw\'r cod a ddarparwyd yn ddilys neu mae eisoes wedi\'i ddefnyddio.',
+    'before'               => 'Rhaid i\'r :attribute bod yn dyddiad cyn :date.',
+    'between'              => [
+        'numeric' => 'Rhaid i\'r :attribute bod rhwng :min a :max.',
+        'file'    => 'Rhaid i\'r :attribute bod rhwng :min a :max kilobytes.',
+        'string'  => 'Rhaid i\'r :attribute bod rhwng :min a :max cymeriadau.',
+        'array'   => 'Rhaid i\'r :attribute cael rhwng :min a :max o eitemau.',
+    ],
+    'boolean'              => 'Rhaid i :attribute fod yn wir neu ddim.',
+    'confirmed'            => 'Dydi\'r cadarnhad :attribute ddim yn cydfynd.',
+    'date'                 => 'Nid yw\'r :attribute yn dyddiad dilys.',
+    'date_format'          => 'Nid yw\'r :attribute yn cydfynd ar format :format.',
+    'different'            => 'Rhaid i :attribute a :other bod yn wahanol.',
+    'digits'               => 'Rhai i\'r :attribute bod yn :digits o ddigidau.',
+    'digits_between'       => 'Rhaid i\'r :attribute bod rhwng :min a :max o digidau.',
+    'email'                => 'Rhaid i\'r :attribute bod yn cyfeiriad e-bost dilys.',
+    'ends_with' => 'Rhaid i\'r :attribute orffen gydag un o\'r canlynol: :values',
+    'file'                 => 'Rhaid darparu\'r :attribute fel ffeil ddilys.',
+    'filled'               => 'Mae angen llenwi\'r maes :attribute.',
+    'gt'                   => [
+        'numeric' => 'Rhaid i\'r :attribute fod yn fwy na :value.',
+        'file'    => 'Rhaid i\'r :attribute fod yn fwy na :value kilobytes.',
+        'string'  => 'Rhaid i\'r :attribute fod yn fwy na :value cymeriadau.',
+        'array'   => 'Rhaid i\'r :attribute fod yn fwy na :value eitemau.',
+    ],
+    '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.',
+    ],
+    '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.',
+    'safe_url'             => 'The provided link may not be safe.',
+    '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.',
+    'totp'                 => 'The provided code is not valid or has expired.',
+    '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' => [],
+];
index 19693e29a632c6a6cb7efc9bc165871981df871f..adfba7d00fbccb4cc4d1fdff6e1d288292d91c43 100644 (file)
@@ -7,41 +7,45 @@ return [
 
     // Pages
     'page_create'                 => 'oprettede side',
-    'page_create_notification'    => 'Page successfully created',
+    'page_create_notification'    => 'Siden blev oprettet',
     'page_update'                 => 'opdaterede side',
-    'page_update_notification'    => 'Page successfully updated',
+    'page_update_notification'    => 'Siden blev opdateret',
     'page_delete'                 => 'slettede side',
-    'page_delete_notification'    => 'Page successfully deleted',
+    'page_delete_notification'    => 'Siden blev slettet',
     'page_restore'                => 'gendannede side',
-    'page_restore_notification'   => 'Page successfully restored',
+    'page_restore_notification'   => 'Siden blev gendannet',
     'page_move'                   => 'flyttede side',
 
     // Chapters
     'chapter_create'              => 'oprettede kapitel',
-    'chapter_create_notification' => 'Chapter successfully created',
+    'chapter_create_notification' => 'Kapitel blev oprettet',
     'chapter_update'              => 'opdaterede kapitel',
-    'chapter_update_notification' => 'Chapter successfully updated',
+    'chapter_update_notification' => 'Kapitel blev opdateret',
     'chapter_delete'              => 'slettede kapitel',
-    'chapter_delete_notification' => 'Chapter successfully deleted',
+    'chapter_delete_notification' => 'Kapitel blev slettet',
     'chapter_move'                => 'flyttede kapitel',
 
     // Books
     'book_create'                 => 'oprettede bog',
-    'book_create_notification'    => 'Book successfully created',
+    'book_create_notification'    => 'Bogen blev oprettet',
+    'book_create_from_chapter'              => 'omdannede kapitel til bog',
+    'book_create_from_chapter_notification' => 'Kapitel blev omdannet til en bog',
     'book_update'                 => 'opdaterede bog',
-    'book_update_notification'    => 'Book successfully updated',
+    'book_update_notification'    => 'Bogen blev opdateret',
     'book_delete'                 => 'slettede bog',
-    'book_delete_notification'    => 'Book successfully deleted',
+    'book_delete_notification'    => 'Bogen blev slettet',
     'book_sort'                   => 'sorterede bogen',
-    'book_sort_notification'      => 'Book successfully re-sorted',
+    'book_sort_notification'      => 'Bogen blev re-sorteret',
 
     // Bookshelves
-    'bookshelf_create'            => 'created bookshelf',
-    'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create'            => 'oprettede bogreol',
+    'bookshelf_create_notification'    => 'Bogreolen blev oprettet',
+    'bookshelf_create_from_book'    => 'omdannede bog til bogreol',
+    'bookshelf_create_from_book_notification'    => 'Bogen blev omdannet til en bogreal',
     'bookshelf_update'                 => 'opdaterede bogreolen',
-    'bookshelf_update_notification'    => 'Bookshelf successfully updated',
+    'bookshelf_update_notification'    => 'Bogreolen blev opdateret',
     'bookshelf_delete'                 => 'slettede bogreol',
-    'bookshelf_delete_notification'    => 'Bookshelf successfully deleted',
+    'bookshelf_delete_notification'    => 'Bogreolen blev slettet',
 
     // Favourites
     'favourite_add_notification' => '":name" er blevet tilføjet til dine favoritter',
@@ -52,16 +56,16 @@ return [
     'mfa_remove_method_notification' => 'Multi-faktor metode fjernet',
 
     // Webhooks
-    'webhook_create' => 'created webhook',
-    'webhook_create_notification' => 'Webhook successfully created',
-    'webhook_update' => 'updated webhook',
-    'webhook_update_notification' => 'Webhook successfully updated',
-    'webhook_delete' => 'deleted webhook',
-    'webhook_delete_notification' => 'Webhook successfully deleted',
+    'webhook_create' => 'oprettede webhook',
+    'webhook_create_notification' => 'Webhooken blev oprettet',
+    'webhook_update' => 'opdaterede webhooken',
+    'webhook_update_notification' => 'Webhooken blev opdateret',
+    'webhook_delete' => 'slettede webhooken',
+    'webhook_delete_notification' => 'Webhooken blev slettet',
 
     // Users
-    'user_update_notification' => 'User successfully updated',
-    'user_delete_notification' => 'User successfully removed',
+    'user_update_notification' => 'Brugeren blev opdateret',
+    'user_delete_notification' => 'Brugeren blev fjernet',
 
     // Other
     'commented_on'                => 'kommenterede til',
index 7ff3c68ffa28174cdc13030d8cfa1e68efb1e670..43a3f33785da23abd3512ecaaace18a541ee4132 100644 (file)
@@ -21,7 +21,7 @@ return [
     'email' => 'E-mail',
     'password' => 'Adgangskode',
     'password_confirm' => 'Bekræft adgangskode',
-    'password_hint' => 'Must be at least 8 characters',
+    'password_hint' => 'Skal være på mindst 8 karakterer',
     'forgot_password' => 'Glemt Adgangskode?',
     'remember_me' => 'Husk mig',
     'ldap_email_hint' => 'Angiv venligst din kontos e-mail.',
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'E-Mail domænet har ikke adgang til denne applikation',
     'register_success' => 'Tak for din registrering. Du er nu registeret og logget ind.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
@@ -54,7 +59,7 @@ return [
     'email_confirm_text' => 'Bekræft venligst din E-Mail adresse ved at klikke på linket nedenfor:',
     'email_confirm_action' => 'Bekræft E-Mail',
     'email_confirm_send_error' => 'E-Mail-bekræftelse kræves, men systemet kunne ikke sende E-Mailen. Kontakt administratoren for at sikre, at E-Mail er konfigureret korrekt.',
-    'email_confirm_success' => 'Your email has been confirmed! You should now be able to login using this email address.',
+    'email_confirm_success' => 'Din email er blevet bekræftet! Du bør nu kune logge ind med denne emailadresse.',
     'email_confirm_resent' => 'Bekræftelsesmail sendt, tjek venligst din indboks.',
 
     'email_not_confirmed' => 'E-Mail adresse ikke bekræftet',
@@ -71,7 +76,7 @@ return [
     'user_invite_page_welcome' => 'Velkommen til :appName!',
     'user_invite_page_text' => 'For at færdiggøre din konto og få adgang skal du indstille en adgangskode, der bruges til at logge ind på :appName ved fremtidige besøg.',
     'user_invite_page_confirm_button' => 'Bekræft adgangskode',
-    'user_invite_success_login' => 'Password set, you should now be able to login using your set password to access :appName!',
+    'user_invite_success_login' => 'Adgangskoden er sat. Du burde nu kunne logge ind med din angivede adgangskode for at tilgå :appName!',
 
     // Multi-factor Authentication
     'mfa_setup' => 'Opsætning af Multi-faktor godkendelse',
@@ -88,23 +93,23 @@ return [
     'mfa_gen_confirm_and_enable' => 'Bekræft og aktivér',
     'mfa_gen_backup_codes_title' => 'Backup koder opsætning',
     'mfa_gen_backup_codes_desc' => 'Store the below list of codes in a safe place. When accessing the system you\'ll be able to use one of the codes as a second authentication mechanism.',
-    'mfa_gen_backup_codes_download' => 'Download Codes',
-    'mfa_gen_backup_codes_usage_warning' => 'Each code can only be used once',
-    'mfa_gen_totp_title' => 'Mobile App Setup',
+    'mfa_gen_backup_codes_download' => 'Download koder',
+    'mfa_gen_backup_codes_usage_warning' => 'Hver kode kan kun bruges en gang',
+    'mfa_gen_totp_title' => 'Mobil App Setup',
     'mfa_gen_totp_desc' => 'To use multi-factor authentication you\'ll need a mobile application that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.',
     'mfa_gen_totp_scan' => 'Scan the QR code below using your preferred authentication app to get started.',
-    'mfa_gen_totp_verify_setup' => 'Verify Setup',
+    'mfa_gen_totp_verify_setup' => 'Verificer Opsætning',
     'mfa_gen_totp_verify_setup_desc' => 'Verify that all is working by entering a code, generated within your authentication app, in the input box below:',
     'mfa_gen_totp_provide_code_here' => 'Provide your app generated code here',
     'mfa_verify_access' => 'Verify Access',
     'mfa_verify_access_desc' => 'Your user account requires you to confirm your identity via an additional level of verification before you\'re granted access. Verify using one of your configured methods to continue.',
-    'mfa_verify_no_methods' => 'No Methods Configured',
+    'mfa_verify_no_methods' => 'Ingen Metoder Konfigureret',
     'mfa_verify_no_methods_desc' => 'No multi-factor authentication methods could be found for your account. You\'ll need to set up at least one method before you gain access.',
-    'mfa_verify_use_totp' => 'Verify using a mobile app',
-    'mfa_verify_use_backup_codes' => 'Verify using a backup code',
-    'mfa_verify_backup_code' => 'Backup Code',
-    'mfa_verify_backup_code_desc' => 'Enter one of your remaining backup codes below:',
-    'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
+    'mfa_verify_use_totp' => 'Bekræft ved brug af en mobil app',
+    'mfa_verify_use_backup_codes' => 'Bekræft ved hjælp af en backup kode',
+    'mfa_verify_backup_code' => 'Backup Kode',
+    'mfa_verify_backup_code_desc' => 'Indtast en af dine resterende backup koder nedenfor:',
+    'mfa_verify_backup_code_enter_here' => 'Indtast backup kode her',
     'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
     'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
 ];
index 890bbe4b43fa66f2f348071f405f68085e7889b4..bcd02dfc639c487972994beb21bc6189ad150b38 100644 (file)
@@ -45,8 +45,10 @@ return [
     'unfavourite' => 'Fjern som foretrukken',
     'next' => 'Næste',
     'previous' => 'Forrige',
-    'filter_active' => 'Active Filter:',
-    'filter_clear' => 'Clear Filter',
+    'filter_active' => 'Aktivt Filter:',
+    'filter_clear' => 'Nulstil Filter',
+    'download' => 'Hent',
+    'open_in_tab' => 'Åben i ny fane',
 
     // Sort Options
     'sort_options' => 'Sorteringsindstillinger',
@@ -72,10 +74,10 @@ return [
     'default' => 'Standard',
     'breadcrumb' => 'Brødkrumme',
     'status' => 'Status',
-    'status_active' => 'Active',
-    'status_inactive' => 'Inactive',
-    'never' => 'Never',
-    'none' => 'None',
+    'status_active' => 'Aktiv',
+    'status_inactive' => 'Inaktiv',
+    'never' => 'Aldrig',
+    'none' => 'Ingen',
 
     // Header
     'header_menu_expand' => 'Udvid header menu',
index 82712029210ebeec005dbf5530d8ad4c0918c042..0c7763727c0b6fe5e696c266fb506ad01f272839 100644 (file)
  */
 return [
     // General editor terms
-    'general' => 'General',
-    'advanced' => 'Advanced',
-    'none' => 'None',
-    'cancel' => 'Cancel',
-    'save' => 'Save',
-    'close' => 'Close',
-    'undo' => 'Undo',
+    'general' => 'Generel',
+    'advanced' => 'Avanceret',
+    'none' => 'Ingen',
+    'cancel' => 'Annuller',
+    'save' => 'Gem',
+    'close' => 'Luk',
+    'undo' => 'Fortryd',
     'redo' => 'Redo',
-    'left' => 'Left',
-    'center' => 'Center',
-    'right' => 'Right',
+    'left' => 'Venstre',
+    'center' => 'Midten',
+    'right' => 'Højre',
     'top' => 'Top',
-    'middle' => 'Middle',
-    'bottom' => 'Bottom',
-    'width' => 'Width',
-    'height' => 'Height',
-    'More' => 'More',
-    'select' => 'Select...',
+    'middle' => 'Midt',
+    'bottom' => 'Bund',
+    'width' => 'Bredde',
+    'height' => 'Højde',
+    'More' => 'Mere',
+    'select' => 'Vælg...',
 
     // Toolbar
-    'formats' => 'Formats',
-    'header_large' => 'Large Header',
-    'header_medium' => 'Medium Header',
-    'header_small' => 'Small Header',
+    'formats' => 'Formater',
+    'header_large' => 'Stor Overskrift',
+    'header_medium' => 'Mellemstor Overskrift',
+    'header_small' => 'Lille Overskrift',
     'header_tiny' => 'Tiny Header',
-    'paragraph' => 'Paragraph',
-    'blockquote' => 'Blockquote',
-    'inline_code' => 'Inline code',
+    'paragraph' => 'Paragraf',
+    'blockquote' => 'Citat',
+    'inline_code' => 'Inline kode',
     'callouts' => 'Callouts',
     'callout_information' => 'Information',
-    'callout_success' => 'Success',
-    'callout_warning' => 'Warning',
-    'callout_danger' => 'Danger',
-    'bold' => 'Bold',
-    'italic' => 'Italic',
-    'underline' => 'Underline',
-    'strikethrough' => 'Strikethrough',
-    'superscript' => 'Superscript',
-    'subscript' => 'Subscript',
-    'text_color' => 'Text color',
-    'custom_color' => 'Custom color',
-    'remove_color' => 'Remove color',
-    'background_color' => 'Background color',
-    'align_left' => 'Align left',
-    'align_center' => 'Align center',
-    'align_right' => 'Align right',
-    'align_justify' => 'Justify',
-    'list_bullet' => 'Bullet list',
-    'list_numbered' => 'Numbered list',
-    'list_task' => 'Task list',
-    'indent_increase' => 'Increase indent',
-    'indent_decrease' => 'Decrease indent',
-    'table' => 'Table',
+    'callout_success' => 'Succes',
+    'callout_warning' => 'Advarsel',
+    'callout_danger' => 'Fare',
+    'bold' => 'Fed',
+    'italic' => 'Kursiv',
+    'underline' => 'Understreget',
+    'strikethrough' => 'Gennemstreget',
+    'superscript' => 'Hævet',
+    'subscript' => 'Sænket',
+    'text_color' => 'Tekstfarve',
+    'custom_color' => 'Tilpasset farve',
+    'remove_color' => 'Fjern farve',
+    'background_color' => 'Baggrundsfarve',
+    'align_left' => 'Venstrejusteret',
+    'align_center' => 'Centrér',
+    'align_right' => 'Højrejusteret',
+    'align_justify' => 'Juster',
+    'list_bullet' => 'Punktliste',
+    'list_numbered' => 'Nummereret liste',
+    'list_task' => 'Opgaveliste',
+    'indent_increase' => 'Forøg indrykning',
+    'indent_decrease' => 'Formindsk indrykning',
+    'table' => 'Tabel',
     'insert_image' => 'Insert image',
     'insert_image_title' => 'Insert/Edit Image',
-    'insert_link' => 'Insert/edit link',
-    'insert_link_title' => 'Insert/Edit Link',
-    'insert_horizontal_line' => 'Insert horizontal line',
-    'insert_code_block' => 'Insert code block',
-    'insert_drawing' => 'Insert/edit drawing',
+    'insert_link' => 'Indsæt/rediger link',
+    'insert_link_title' => 'Indsæt/Rediger Link',
+    'insert_horizontal_line' => 'Indsæt vandret linje',
+    'insert_code_block' => 'Indsæt kodeblok',
+    'insert_drawing' => 'Indsæt/rediger tegning',
     'drawing_manager' => 'Drawing manager',
-    'insert_media' => 'Insert/edit media',
-    'insert_media_title' => 'Insert/Edit Media',
-    'clear_formatting' => 'Clear formatting',
-    'source_code' => 'Source code',
-    'source_code_title' => 'Source Code',
-    'fullscreen' => 'Fullscreen',
+    'insert_media' => 'Indsæt/rediger medie',
+    'insert_media_title' => 'Indsæt/Rediger Medie',
+    'clear_formatting' => 'Ryd formatering',
+    'source_code' => 'Kildekode',
+    'source_code_title' => 'Kildekode',
+    'fullscreen' => 'Fuld skærm',
     'image_options' => 'Image options',
 
     // Tables
-    'table_properties' => 'Table properties',
-    'table_properties_title' => 'Table Properties',
-    'delete_table' => 'Delete table',
-    'insert_row_before' => 'Insert row before',
-    'insert_row_after' => 'Insert row after',
-    'delete_row' => 'Delete row',
-    'insert_column_before' => 'Insert column before',
-    'insert_column_after' => 'Insert column after',
-    'delete_column' => 'Delete column',
-    'table_cell' => 'Cell',
-    'table_row' => 'Row',
-    'table_column' => 'Column',
-    'cell_properties' => 'Cell properties',
-    'cell_properties_title' => 'Cell Properties',
-    'cell_type' => 'Cell type',
-    'cell_type_cell' => 'Cell',
+    'table_properties' => 'Tabelegenskaber',
+    'table_properties_title' => 'Tabelegenskaber',
+    'delete_table' => 'Slet tabel',
+    'insert_row_before' => 'Indsæt række før',
+    'insert_row_after' => 'Indsæt række efter',
+    'delete_row' => 'Slet række',
+    'insert_column_before' => 'Indsæt kolonne før',
+    'insert_column_after' => 'Indsæt kolonne efter',
+    'delete_column' => 'Slet kolonne',
+    'table_cell' => 'Celle',
+    'table_row' => 'Række',
+    'table_column' => 'Kolonne',
+    'cell_properties' => 'Celle egenskaber',
+    'cell_properties_title' => 'Celle Egenskaber',
+    'cell_type' => 'Celle type',
+    'cell_type_cell' => 'Celle',
     'cell_scope' => 'Scope',
     'cell_type_header' => 'Header cell',
-    'merge_cells' => 'Merge cells',
-    'split_cell' => 'Split cell',
-    'table_row_group' => 'Row Group',
-    'table_column_group' => 'Column Group',
-    'horizontal_align' => 'Horizontal align',
-    'vertical_align' => 'Vertical align',
-    'border_width' => 'Border width',
-    'border_style' => 'Border style',
-    'border_color' => 'Border color',
-    'row_properties' => 'Row properties',
-    'row_properties_title' => 'Row Properties',
-    'cut_row' => 'Cut row',
-    'copy_row' => 'Copy row',
-    'paste_row_before' => 'Paste row before',
-    'paste_row_after' => 'Paste row after',
-    'row_type' => 'Row type',
-    'row_type_header' => 'Header',
-    'row_type_body' => 'Body',
-    'row_type_footer' => 'Footer',
-    'alignment' => 'Alignment',
-    'cut_column' => 'Cut column',
-    'copy_column' => 'Copy column',
-    'paste_column_before' => 'Paste column before',
-    'paste_column_after' => 'Paste column after',
+    'merge_cells' => 'Flet celler',
+    'split_cell' => 'Opdel celle',
+    'table_row_group' => 'Række Gruppe',
+    'table_column_group' => 'Kolonne Gruppe',
+    'horizontal_align' => 'Juster vandret',
+    'vertical_align' => 'Juster lodret',
+    'border_width' => 'Kantbredde',
+    'border_style' => 'Kantstil',
+    'border_color' => 'Kantfarve',
+    'row_properties' => 'Række egenskaber',
+    'row_properties_title' => 'Række Egenskaber',
+    'cut_row' => 'Klip række',
+    'copy_row' => 'Kopier række',
+    'paste_row_before' => 'Indsæt række før',
+    'paste_row_after' => 'Indsæt række efter',
+    'row_type' => 'Række type',
+    'row_type_header' => 'Overskrift',
+    'row_type_body' => 'Krop',
+    'row_type_footer' => 'Sidefod',
+    'alignment' => 'Justering',
+    'cut_column' => 'Klip kolonne',
+    'copy_column' => 'Kopier kolonne',
+    'paste_column_before' => 'Indsæt kolonne før',
+    'paste_column_after' => 'Indsæt kolonne efter',
     'cell_padding' => 'Cell padding',
     'cell_spacing' => 'Cell spacing',
     'caption' => 'Caption',
     'show_caption' => 'Show caption',
     'constrain' => 'Constrain proportions',
     'cell_border_solid' => 'Solid',
-    'cell_border_dotted' => 'Dotted',
-    'cell_border_dashed' => 'Dashed',
-    'cell_border_double' => 'Double',
+    'cell_border_dotted' => 'Prikket',
+    'cell_border_dashed' => 'Stiplet',
+    'cell_border_double' => 'Dobbelt',
     'cell_border_groove' => 'Groove',
     'cell_border_ridge' => 'Ridge',
     'cell_border_inset' => 'Inset',
     'cell_border_outset' => 'Outset',
-    'cell_border_none' => 'None',
-    'cell_border_hidden' => 'Hidden',
+    'cell_border_none' => 'Ingen',
+    'cell_border_hidden' => 'Gemt',
 
     // Images, links, details/summary & embed
-    'source' => 'Source',
-    'alt_desc' => 'Alternative description',
+    'source' => 'Kilde',
+    'alt_desc' => 'Alternativ beskrivelse',
     'embed' => 'Embed',
     'paste_embed' => 'Paste your embed code below:',
     'url' => 'URL',
-    'text_to_display' => 'Text to display',
-    'title' => 'Title',
-    'open_link' => 'Open link in...',
-    'open_link_current' => 'Current window',
-    'open_link_new' => 'New window',
+    'text_to_display' => 'Tekst til visning',
+    'title' => 'Titel',
+    'open_link' => 'Åben link i...',
+    'open_link_current' => 'Nuværende vindue',
+    'open_link_new' => 'Nyt vindue',
     'insert_collapsible' => 'Insert collapsible block',
     'collapsible_unwrap' => 'Unwrap',
     'edit_label' => 'Edit label',
@@ -159,13 +159,13 @@ return [
     'editor_license' => 'Editor License & Copyright',
     'editor_tiny_license' => 'This editor is built using :tinyLink which is provided under an LGPL v2.1 license.',
     'editor_tiny_license_link' => 'The copyright and license details of TinyMCE can be found here.',
-    'save_continue' => 'Save Page & Continue',
+    'save_continue' => 'Gem og fortsæt',
     'callouts_cycle' => '(Keep pressing to toggle through types)',
     'link_selector' => 'Link to content',
-    'shortcuts' => 'Shortcuts',
-    'shortcut' => 'Shortcut',
-    'shortcuts_intro' => 'The following shortcuts are available in the editor:',
+    'shortcuts' => 'Genveje',
+    'shortcut' => 'Genvej',
+    'shortcuts_intro' => 'Følgende genveje er tilgængelige i editoren:',
     'windows_linux' => '(Windows/Linux)',
     'mac' => '(Mac)',
-    'description' => 'Description',
+    'description' => 'Beskrivelse',
 ];
index 1766dede5185487710867b2a2f536eb251f036c7..529dbbcac1db60c7da3a8b5c51ab8bfa62b55e61 100644 (file)
@@ -143,8 +143,8 @@ return [
     'books_sort_chapters_last' => 'Kapitler sidst',
     'books_sort_show_other' => 'Vis andre bøger',
     'books_sort_save' => 'Gem ny ordre',
-    'books_copy' => 'Copy Book',
-    'books_copy_success' => 'Book successfully copied',
+    'books_copy' => 'Kopier Bog',
+    'books_copy_success' => 'Bogen blev kopieret',
 
     // Chapters
     'chapter' => 'Kapitel',
@@ -163,8 +163,8 @@ return [
     'chapters_move' => 'Flyt kapitel',
     'chapters_move_named' => 'Flyt kapitel :chapterName',
     'chapter_move_success' => 'Kapitel flyttet til :bookName',
-    'chapters_copy' => 'Copy Chapter',
-    'chapters_copy_success' => 'Chapter successfully copied',
+    'chapters_copy' => 'Kopier Kapitel',
+    'chapters_copy_success' => 'Kapitlet blev kopieret',
     'chapters_permissions' => 'Kapiteltilladelser',
     'chapters_empty' => 'Der er lige nu ingen sider i dette kapitel.',
     'chapters_permissions_active' => 'Aktive kapiteltilladelser',
@@ -196,14 +196,14 @@ return [
     'pages_edit_draft_save_at' => 'Kladde gemt ved ',
     'pages_edit_delete_draft' => 'Slet kladde',
     'pages_edit_discard_draft' => 'Kassér kladde',
-    'pages_edit_switch_to_markdown' => 'Switch to Markdown Editor',
+    'pages_edit_switch_to_markdown' => 'Skift til Markdown redigering',
     'pages_edit_switch_to_markdown_clean' => '(Clean Content)',
     'pages_edit_switch_to_markdown_stable' => '(Stable Content)',
-    'pages_edit_switch_to_wysiwyg' => 'Switch to WYSIWYG Editor',
+    'pages_edit_switch_to_wysiwyg' => 'Skift til WYSIWYG redigering',
     'pages_edit_set_changelog' => 'Sæt ændringsoversigt',
     'pages_edit_enter_changelog_desc' => 'Indtast en kort beskrivelse af ændringer du har lavet',
     'pages_edit_enter_changelog' => 'Indtast ændringsoversigt',
-    'pages_editor_switch_title' => 'Switch Editor',
+    'pages_editor_switch_title' => 'Skift Editor',
     'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?',
     'pages_editor_switch_consider_following' => 'Consider the following when changing editors:',
     'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.',
@@ -249,7 +249,7 @@ return [
     'pages_initial_name' => 'Ny side',
     'pages_editing_draft_notification' => 'Du redigerer en kladde der sidst var gemt :timeDiff.',
     'pages_draft_edited_notification' => 'Siden har været opdateret siden da. Det er anbefalet at du kasserer denne kladde.',
-    'pages_draft_page_changed_since_creation' => 'This page has been updated since this draft was created. It is recommended that you discard this draft or take care not to overwrite any page changes.',
+    'pages_draft_page_changed_since_creation' => 'Denne side er blevet opdateret siden dette udkast blev oprettet. Det anbefales at du kasserer dette udkast eller passer på ikke at overskrive nogen sideændringer.',
     'pages_draft_edit_active' => [
         'start_a' => ':count brugerer har begyndt at redigere denne side',
         'start_b' => ':userName er begyndt at redigere denne side',
@@ -274,14 +274,14 @@ return [
     'tags_add' => 'Tilføj endnu et tag',
     'tags_remove' => 'Fjern dette tag',
     'tags_usages' => 'Total tag usages',
-    'tags_assigned_pages' => 'Assigned to Pages',
-    'tags_assigned_chapters' => 'Assigned to Chapters',
-    'tags_assigned_books' => 'Assigned to Books',
-    'tags_assigned_shelves' => 'Assigned to Shelves',
-    'tags_x_unique_values' => ':count unique values',
-    'tags_all_values' => 'All values',
-    'tags_view_tags' => 'View Tags',
-    'tags_view_existing_tags' => 'View existing tags',
+    'tags_assigned_pages' => 'Tildelt til sider',
+    'tags_assigned_chapters' => 'Tildelt til Kapitler',
+    'tags_assigned_books' => 'Tildelt til Bøger',
+    'tags_assigned_shelves' => 'Tildelt til bogreoler',
+    'tags_x_unique_values' => ':count unikke værdier',
+    'tags_all_values' => 'Alle værdier',
+    'tags_view_tags' => 'Vis Tags',
+    'tags_view_existing_tags' => 'Vis eksisterende tags',
     'tags_list_empty_hint' => 'Tags can be assigned via the page editor sidebar or while editing the details of a book, chapter or shelf.',
     'attachments' => 'Vedhæftninger',
     'attachments_explain' => 'Upload nogle filer, eller vedhæft nogle links, der skal vises på siden. Disse er synlige i sidepanelet.',
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Omdan Bog',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Omdan til Bog',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Omdan Kapitel',
+    'convert_chapter_confirm' => 'Er du sikker på at du vil omdanne dette kapitel?',
 ];
index 2d3c5522eee35bd35e9fccde7e19a4e5aabe8aac..a6920ce64908a25740733f2830332f55e479e79c 100644 (file)
@@ -10,8 +10,8 @@ return [
     'settings' => 'Indstillinger',
     'settings_save' => 'Gem indstillinger',
     'settings_save_success' => 'Indstillingerne blev gemt',
-    'system_version' => 'System Version',
-    'categories' => 'Categories',
+    'system_version' => 'Systemversion',
+    'categories' => 'Kategorier',
 
     // App Settings
     'app_customization' => 'Tilpasning',
@@ -27,8 +27,8 @@ return [
     'app_secure_images' => 'Højere sikkerhed for billeduploads',
     'app_secure_images_toggle' => 'Aktiver højere sikkerhed for billeduploads',
     'app_secure_images_desc' => 'Af performanceårsager er alle billeder offentlige. Denne funktion tilføjer en tilfældig, vanskelig at gætte streng foran billed-url\'er. Sørg for, at mappeindeksering ikke er aktiveret for at forhindre nem adgang.',
-    'app_default_editor' => 'Default Page Editor',
-    'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.',
+    'app_default_editor' => 'Standard Side Editor',
+    'app_default_editor_desc' => 'Vælg hvilken editor der som standard skal bruges ved redigering af nye sider. Dette kan tilsidesættes på side niveau, hvor tilladelser tillader det.',
     'app_custom_html' => 'Tilpasset HTML head indhold',
     'app_custom_html_desc' => 'Alt indhold tilføjet her, vil blive indsat i bunden af <head> sektionen på alle sider. Dette er brugbart til overskrivning af styles og tilføjelse af analytics kode.',
     'app_custom_html_disabled_notice' => 'Brugerdefineret HTML head indhold er deaktiveret på denne indstillingsside for at, at ændringer kan rulles tilbage.',
@@ -152,7 +152,7 @@ return [
     'role_access_api' => 'Tilgå system-API',
     'role_manage_settings' => 'Administrer app-indstillinger',
     'role_export_content' => 'Eksporter indhold',
-    'role_editor_change' => 'Change page editor',
+    'role_editor_change' => 'Skift side editor',
     'role_asset' => 'Tilladelser for medier og "assets"',
     'roles_system_warning' => 'Vær opmærksom på, at adgang til alle af de ovennævnte tre tilladelser, kan give en bruger mulighed for at ændre deres egne brugerrettigheder eller brugerrettigheder for andre i systemet. Tildel kun roller med disse tilladelser til betroede brugere.',
     'role_asset_desc' => 'Disse tilladelser kontrollerer standardadgang til medier og "assets" i systemet. Tilladelser til bøger, kapitler og sider tilsidesætter disse tilladelser.',
@@ -177,7 +177,7 @@ return [
     'users_role' => 'Brugerroller',
     'users_role_desc' => 'Vælg hvilke roller denne bruger skal tildeles. Hvis en bruger er tildelt flere roller, sammenføres tilladelserne fra disse roller, og de får alle evnerne fra de tildelte roller.',
     'users_password' => 'Brugeradgangskode',
-    'users_password_desc' => 'Set a password used to log-in to the application. This must be at least 8 characters long.',
+    'users_password_desc' => 'Sæt et kodeord, der bruges til at logge på applikationen. Dette skal være mindst 8 tegn langt.',
     'users_send_invite_text' => 'Du kan vælge at sende denne bruger en invitation på E-Mail, som giver dem mulighed for at indstille deres egen adgangskode, ellers kan du indstille deres adgangskode selv.',
     'users_send_invite_option' => 'Send bruger en invitationsmail',
     'users_external_auth_id' => 'Ekstern godkendelses ID',
@@ -236,30 +236,30 @@ return [
 
     // Webhooks
     'webhooks' => 'Webhooks',
-    'webhooks_create' => 'Create New Webhook',
-    'webhooks_none_created' => 'No webhooks have yet been created.',
-    'webhooks_edit' => 'Edit Webhook',
-    'webhooks_save' => 'Save Webhook',
-    'webhooks_details' => 'Webhook Details',
-    'webhooks_details_desc' => 'Provide a user friendly name and a POST endpoint as a location for the webhook data to be sent to.',
-    'webhooks_events' => 'Webhook Events',
-    'webhooks_events_desc' => 'Select all the events that should trigger this webhook to be called.',
-    'webhooks_events_warning' => 'Keep in mind that these events will be triggered for all selected events, even if custom permissions are applied. Ensure that use of this webhook won\'t expose confidential content.',
-    'webhooks_events_all' => 'All system events',
-    'webhooks_name' => 'Webhook Name',
-    'webhooks_timeout' => 'Webhook Request Timeout (Seconds)',
+    'webhooks_create' => 'Opret ny Webhook',
+    'webhooks_none_created' => 'Ingen webhooks er blevet oprettet endnu.',
+    'webhooks_edit' => 'Rediger Webhook',
+    'webhooks_save' => 'Gem Webhook',
+    'webhooks_details' => 'Webhook detaljer',
+    'webhooks_details_desc' => 'Angiv et brugervenligt navn og et POST endpoint som en lokation for webhook data at blive sendt til.',
+    'webhooks_events' => 'Webhook Begivenheder',
+    'webhooks_events_desc' => 'Vælg alle begivenhederd er skal udløse denne webhook til at blive kaldt.',
+    'webhooks_events_warning' => 'Husk, at disse begivenheder vil blive udløst for alle valgte begivenheder, selv om brugerdefinerede tilladelser bliver anvendt. Sørg for, at brugen af denne webhook ikke vil afsløre fortroligt indhold.',
+    'webhooks_events_all' => 'Alle systemhændelser',
+    'webhooks_name' => 'Webhook Navn',
+    'webhooks_timeout' => 'Webhook forespørgsel timeout (Sekunder)',
     'webhooks_endpoint' => 'Webhook Endpoint',
-    'webhooks_active' => 'Webhook Active',
-    'webhook_events_table_header' => 'Events',
-    'webhooks_delete' => 'Delete Webhook',
-    'webhooks_delete_warning' => 'This will fully delete this webhook, with the name \':webhookName\', from the system.',
-    'webhooks_delete_confirm' => 'Are you sure you want to delete this webhook?',
-    'webhooks_format_example' => 'Webhook Format Example',
-    'webhooks_format_example_desc' => 'Webhook data is sent as a POST request to the configured endpoint as JSON following the format below. The "related_item" and "url" properties are optional and will depend on the type of event triggered.',
+    'webhooks_active' => 'Webhook Aktiv',
+    'webhook_events_table_header' => 'Begivenheder',
+    'webhooks_delete' => 'Slet Webhook',
+    'webhooks_delete_warning' => 'Dette vil helt slette denne webhook med navnet \':webhookName\' fra systemet.',
+    'webhooks_delete_confirm' => 'Er du sikker på at du vil slette denne webhook?',
+    'webhooks_format_example' => 'Webhook format eksempel',
+    'webhooks_format_example_desc' => 'Webhook data bliver sendt som en POST anmodning til det konfigurerede endpoint som JSON efter formatet nedenfor. Egenskaberne "related_item" og "url" er valgri og vil afhænge af den type begivenhed udløst.',
     'webhooks_status' => 'Webhook Status',
-    'webhooks_last_called' => 'Last Called:',
-    'webhooks_last_errored' => 'Last Errored:',
-    'webhooks_last_error_message' => 'Last Error Message:',
+    'webhooks_last_called' => 'Sidst Kaldt:',
+    'webhooks_last_errored' => 'Sidst Fejlet:',
+    'webhooks_last_error_message' => 'Sidste fejlmeddelelse:',
 
 
     //! If editing translations files directly please ignore this in all
index 649e0df33c63aafb7e007841b94035eb72afcbb6..022839dc693ab6635123e70af9c4ebe3f085139d 100644 (file)
@@ -32,7 +32,7 @@ return [
     'digits_between'       => ':attribute skal være mellem :min og :max cifre.',
     'email'                => ':attribute skal være en gyldig mail-adresse.',
     'ends_with' => ':attribute skal slutte på en af følgende værdier: :values',
-    'file'                 => 'The :attribute must be provided as a valid file.',
+    'file'                 => ':attribute skal leveres som en gyldig fil.',
     'filled'               => ':attribute er obligatorisk.',
     'gt'                   => [
         'numeric' => ':attribute skal være større end :value.',
index f7481420370423131e96f4727a8b01a794774fb1..fc7291a5d5d2d912883256657d22c164001f5323 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'hat das Buch erstellt',
     'book_create_notification'    => 'Das Buch wurde erfolgreich erstellt',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'hat das Buch aktualisiert',
     'book_update_notification'    => 'Das Buch wurde erfolgreich aktualisiert',
     'book_delete'                 => 'hat das Buch gelöscht',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'erstelltes Bücherregal',
     'bookshelf_create_notification'    => 'Das Bücherregal wurde erfolgreich erstellt',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'hat das Bücherregal geändert',
     'bookshelf_update_notification'    => 'Das Bücherregal wurde erfolgreich geändert',
     'bookshelf_delete'                 => 'hat das Bücherregal gelöscht',
index 44c2887aadc3ae9abb5eeca4edc1be3e496cdba9..3005fd93cc8240b44e5085d67eb41514b3d7467f 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Sie können sich mit dieser E-Mail nicht registrieren.',
     'register_success' => 'Vielen Dank für Ihre Registrierung! Die Daten sind gespeichert und Sie sind angemeldet.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
index ce8170ed225d87cfe3efd8fc005242da12f83dd0..24f655339e7143bd3fc909387bd8f9f4fc589422 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Vorheriges',
     'filter_active' => 'Gesetzte Filter:',
     'filter_clear' => 'Filter löschen',
+    'download' => 'Herunterladen',
+    'open_in_tab' => 'In Neuem Tab öffnen',
 
     // Sort Options
     'sort_options' => 'Sortieroptionen',
index e6f06a0b16c34f6831d22b4da09b7353d54ed1b3..158697c26ab47be22596a28892d54508664f9ce9 100644 (file)
@@ -196,19 +196,19 @@ return [
     'pages_edit_draft_save_at' => 'Entwurf gespeichert um ',
     'pages_edit_delete_draft' => 'Entwurf löschen',
     'pages_edit_discard_draft' => 'Entwurf verwerfen',
-    'pages_edit_switch_to_markdown' => 'Switch to Markdown Editor',
-    'pages_edit_switch_to_markdown_clean' => '(Clean Content)',
-    'pages_edit_switch_to_markdown_stable' => '(Stable Content)',
-    'pages_edit_switch_to_wysiwyg' => 'Switch to WYSIWYG Editor',
+    'pages_edit_switch_to_markdown' => 'Zum Markdown Editor wechseln',
+    'pages_edit_switch_to_markdown_clean' => '(gesäuberter Output)',
+    'pages_edit_switch_to_markdown_stable' => '(html beibehalten)',
+    'pages_edit_switch_to_wysiwyg' => 'Wechseln Sie zum WYSIWYG-Editor',
     'pages_edit_set_changelog' => 'Änderungsprotokoll hinzufügen',
     'pages_edit_enter_changelog_desc' => 'Bitte geben Sie eine kurze Zusammenfassung Ihrer Änderungen ein',
     'pages_edit_enter_changelog' => 'Änderungsprotokoll eingeben',
-    'pages_editor_switch_title' => 'Switch Editor',
-    'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?',
-    'pages_editor_switch_consider_following' => 'Consider the following when changing editors:',
-    'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.',
-    'pages_editor_switch_consideration_b' => 'This can potentially lead to a loss of detail and syntax in certain circumstances.',
-    'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.',
+    'pages_editor_switch_title' => 'Editor wechseln',
+    'pages_editor_switch_are_you_sure' => 'Sind Sie sicher, dass Sie den Editor für diese Seite ändern möchten?',
+    'pages_editor_switch_consider_following' => 'Betrachten Sie folgendes beim Ändern von Editoren:',
+    'pages_editor_switch_consideration_a' => 'Einmal gespeichert, wird die neue Editoroption von zukünftigen Editoren verwendet, einschließlich derjenigen, die nicht in der Lage sind, den Editortyp selbst zu ändern.',
+    'pages_editor_switch_consideration_b' => 'Dies kann unter bestimmten Umständen zu einem Verlust von Details und Quellcode führen.',
+    'pages_editor_switch_consideration_c' => 'Änderungen des Tags oder Änderungsprotokolls, die seit dem letzten Speichern vorgenommen wurden, werden bei dieser Änderung nicht fortgesetzt.',
     'pages_save' => 'Seite speichern',
     'pages_title' => 'Seitentitel',
     'pages_name' => 'Seitenname',
@@ -235,7 +235,7 @@ return [
     'pages_revisions_number' => '#',
     'pages_revisions_numbered' => 'Revision #:id',
     'pages_revisions_numbered_changes' => 'Revision #:id Änderungen',
-    'pages_revisions_editor' => 'Editor Type',
+    'pages_revisions_editor' => 'Editor-Typ',
     'pages_revisions_changelog' => 'Änderungsprotokoll',
     'pages_revisions_changes' => 'Änderungen',
     'pages_revisions_current' => 'Aktuelle Version',
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Bilder auf der Seite werden nicht dupliziert und die originalen Bilder werden die Beziehung zur ursprünglichen Seite, auf der sie hochgeladen wurden, behalten.',
     'copy_consider_attachments' => 'Seitenanhänge werden nicht kopiert.',
     'copy_consider_access' => 'Eine Veränderung der Position, Besitzers oder Berechtigungen könnte dafür sorgen, dass Unberechtigte, Zugriff bekommen.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index fac489dfbe20bb65c8aa136b4eb88d65fa8464de..e69f7291708989e09f001dc38d03fc0ef29fde4f 100644 (file)
@@ -27,8 +27,8 @@ return [
     'app_secure_images' => 'Erhöhte Sicherheit für hochgeladene Bilder aktivieren?',
     'app_secure_images_toggle' => 'Aktiviere Bild-Upload höherer Sicherheit',
     'app_secure_images_desc' => 'Aus Leistungsgründen sind alle Bilder öffentlich sichtbar. Diese Option fügt zufällige, schwer zu eratene, Zeichenketten zu Bild-URLs hinzu. Stellen sie sicher, dass Verzeichnisindizes deaktiviert sind, um einen einfachen Zugriff zu verhindern.',
-    'app_default_editor' => 'Default Page Editor',
-    'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.',
+    'app_default_editor' => 'Standard-Seiten-Editor',
+    'app_default_editor_desc' => 'Wählen Sie aus, welcher Editor standardmäßig beim Bearbeiten neuer Seiten verwendet wird. Dies kann auf einer Seitenebene überschrieben werden, wenn es die Berechtigungen erlauben.',
     'app_custom_html' => 'Benutzerdefinierter HTML <head> Inhalt',
     'app_custom_html_desc' => 'Jeder Inhalt, der hier hinzugefügt wird, wird am Ende der <head> Sektion jeder Seite eingefügt. Diese kann praktisch sein, um CSS Styles anzupassen oder Analytics-Code hinzuzufügen.',
     'app_custom_html_disabled_notice' => 'Benutzerdefinierte HTML-Kopfzeileninhalte sind auf dieser Einstellungsseite deaktiviert, um sicherzustellen, dass alle Änderungen rückgängig gemacht werden können.',
@@ -155,7 +155,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 
     'role_access_api' => 'Systemzugriffs-API',
     'role_manage_settings' => 'Globaleinstellungen verwalten',
     'role_export_content' => 'Inhalt exportieren',
-    'role_editor_change' => 'Change page editor',
+    'role_editor_change' => 'Seiten-Editor ändern',
     'role_asset' => 'Berechtigungen',
     'roles_system_warning' => 'Beachten Sie, dass der Zugriff auf eine der oben genannten drei Berechtigungen einem Benutzer erlauben kann, seine eigenen Berechtigungen oder die Rechte anderer im System zu ändern. Weisen Sie nur Rollen, mit diesen Berechtigungen, vertrauenswürdigen Benutzern zu.',
     'role_asset_desc' => 'Diese Berechtigungen gelten für den Standard-Zugriff innerhalb des Systems. Berechtigungen für Bücher, Kapitel und Seiten überschreiben diese Berechtigungenen.',
index d5ee91380e83c211f311a4a25bc744a830523bf8..ba39eb7f47dbfb7211bbb82b84af1f138e03567f 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'erstellt Buch',
     'book_create_notification'    => 'Das Buch wurde erfolgreich erstellt',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'aktualisiert Buch',
     'book_update_notification'    => 'Das Buch wurde erfolgreich aktualisiert',
     'book_delete'                 => 'löscht Buch',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'erstelltes Bücherregal',
     'bookshelf_create_notification'    => 'Das Bücherregal wurde erfolgreich erstellt',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'aktualisiert Bücherregal',
     'bookshelf_update_notification'    => 'Das Bücherregal wurde erfolgreich geändert',
     'bookshelf_delete'                 => 'löscht Bücherregal',
index 7191be8328543ed901c545b27e83012083498435..dac76e3908cc36b8b2f291428ef5d84e795f0b68 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Du kannst dich mit dieser E-Mail nicht registrieren.',
     'register_success' => 'Vielen Dank für deine Registrierung! Du bist jetzt registriert und eingeloggt.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
index ffe5594d73880ebf0890c497dbdb0d677fcfe3fe..1d92bda7c59ec7f1befe2da918216f521cbc1459 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Vorheriges',
     'filter_active' => 'Gesetzte Filter:',
     'filter_clear' => 'Filter löschen',
+    'download' => 'Herunterladen',
+    'open_in_tab' => 'In Neuem Tab öffnen',
 
     // Sort Options
     'sort_options' => 'Sortieroptionen',
index 165afd4f5de582f70303b7f2881151948174e2a1..74282a77a78983d04b79cc25fdee01dacb7a1741 100644 (file)
@@ -196,19 +196,19 @@ return [
     'pages_edit_draft_save_at' => 'Entwurf gespeichert um ',
     'pages_edit_delete_draft' => 'Entwurf löschen',
     'pages_edit_discard_draft' => 'Entwurf verwerfen',
-    'pages_edit_switch_to_markdown' => 'Switch to Markdown Editor',
-    'pages_edit_switch_to_markdown_clean' => '(Clean Content)',
-    'pages_edit_switch_to_markdown_stable' => '(Stable Content)',
-    'pages_edit_switch_to_wysiwyg' => 'Switch to WYSIWYG Editor',
+    'pages_edit_switch_to_markdown' => 'Zum Markdown Editor wechseln',
+    'pages_edit_switch_to_markdown_clean' => '(gesäuberter Output)',
+    'pages_edit_switch_to_markdown_stable' => '(html beibehalten)',
+    'pages_edit_switch_to_wysiwyg' => 'Wechseln Sie zum WYSIWYG-Editor',
     'pages_edit_set_changelog' => 'Änderungsprotokoll hinzufügen',
     'pages_edit_enter_changelog_desc' => 'Bitte gib eine kurze Zusammenfassung Deiner Änderungen ein',
     'pages_edit_enter_changelog' => 'Änderungsprotokoll eingeben',
-    'pages_editor_switch_title' => 'Switch Editor',
-    'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?',
-    'pages_editor_switch_consider_following' => 'Consider the following when changing editors:',
-    'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.',
-    'pages_editor_switch_consideration_b' => 'This can potentially lead to a loss of detail and syntax in certain circumstances.',
-    'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.',
+    'pages_editor_switch_title' => 'Editor wechseln',
+    'pages_editor_switch_are_you_sure' => 'Sind Sie sicher, dass Sie den Editor für diese Seite ändern möchten?',
+    'pages_editor_switch_consider_following' => 'Betrachten Sie folgendes beim Ändern von Editoren:',
+    'pages_editor_switch_consideration_a' => 'Einmal gespeichert, wird die neue Editoroption von zukünftigen Editoren verwendet, einschließlich derjenigen, die nicht in der Lage sind, den Editortyp selbst zu ändern.',
+    'pages_editor_switch_consideration_b' => 'Dies kann unter bestimmten Umständen zu einem Verlust von Details und Quellcode führen.',
+    'pages_editor_switch_consideration_c' => 'Änderungen des Tags oder Änderungsprotokolls, die seit dem letzten Speichern vorgenommen wurden, werden bei dieser Änderung nicht fortgesetzt.',
     'pages_save' => 'Seite speichern',
     'pages_title' => 'Seitentitel',
     'pages_name' => 'Seitenname',
@@ -235,7 +235,7 @@ return [
     'pages_revisions_number' => '#',
     'pages_revisions_numbered' => 'Revision #:id',
     'pages_revisions_numbered_changes' => 'Revision #:id Änderungen',
-    'pages_revisions_editor' => 'Editor Type',
+    'pages_revisions_editor' => 'Editor-Typ',
     'pages_revisions_changelog' => 'Änderungsprotokoll',
     'pages_revisions_changes' => 'Änderungen',
     'pages_revisions_current' => 'Aktuelle Version',
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Bilder auf der Seite werden nicht dupliziert und die originalen Bilder werden die Beziehung zur ursprünglichen Seite, auf der sie hochgeladen wurden, behalten.',
     'copy_consider_attachments' => 'Seitenanhänge werden nicht kopiert.',
     'copy_consider_access' => 'Eine Veränderung der Position, Besitzers oder Berechtigungen könnte dafür sorgen, dass Unberechtigte, Zugriff bekommen.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 25b0b6bd17727a6954e9c815c7be85e3319fb52a..6cdeaea193f80362d305d744cf221ac3ec76bdf3 100644 (file)
@@ -27,8 +27,8 @@ return [
     'app_secure_images' => 'Erhöhte Sicherheit für hochgeladene Bilder aktivieren?',
     'app_secure_images_toggle' => 'Aktiviere Bild-Upload mit höherer Sicherheit',
     'app_secure_images_desc' => 'Aus Leistungsgründen sind alle Bilder öffentlich sichtbar. Diese Option fügt zufällige, schwer zu eratene, Zeichenketten zu Bild-URLs hinzu. Stellen sie sicher, dass Verzeichnisindizes deaktiviert sind, um einen einfachen Zugriff zu verhindern.',
-    'app_default_editor' => 'Default Page Editor',
-    'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.',
+    'app_default_editor' => 'Standard-Seiten-Editor',
+    'app_default_editor_desc' => 'Wählen Sie aus, welcher Editor standardmäßig beim Bearbeiten neuer Seiten verwendet wird. Dies kann auf einer Seitenebene überschrieben werden, wenn es die Berechtigungen erlauben.',
     'app_custom_html' => 'Benutzerdefinierter HTML <head> Inhalt',
     'app_custom_html_desc' => 'Jeder Inhalt, der hier hinzugefügt wird, wird am Ende der <head> Sektion jeder Seite eingefügt. Diese kann praktisch sein, um CSS Styles anzupassen oder Analytics-Code hinzuzufügen.',
     'app_custom_html_disabled_notice' => 'Benutzerdefinierte HTML-Kopfzeileninhalte sind auf dieser Einstellungsseite deaktiviert, um sicherzustellen, dass alle Änderungen rückgängig gemacht werden können.',
@@ -155,7 +155,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 
     'role_access_api' => 'Systemzugriffs-API',
     'role_manage_settings' => 'Globaleinstellungen verwalten',
     'role_export_content' => 'Inhalt exportieren',
-    'role_editor_change' => 'Change page editor',
+    'role_editor_change' => 'Seiten-Editor ändern',
     'role_asset' => 'Berechtigungen',
     'roles_system_warning' => 'Beachten Sie, dass der Zugriff auf eine der oben genannten drei Berechtigungen einem Benutzer erlauben kann, seine eigenen Berechtigungen oder die Rechte anderer im System zu ändern. Weisen Sie nur Rollen, mit diesen Berechtigungen, vertrauenswürdigen Benutzern zu.',
     'role_asset_desc' => 'Diese Berechtigungen gelten für den Standard-Zugriff innerhalb des Systems. Berechtigungen für Bücher, Kapitel und Seiten überschreiben diese Berechtigungenen.',
index 77c39b50c8c3be5cb6110c074b016ef9aca122e8..edddf9aebcc6a4cf9c3e70f6b6ea4ebf98d646af 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'created book',
     'book_create_notification'    => 'Book successfully created',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'updated book',
     'book_update_notification'    => 'Book successfully updated',
     'book_delete'                 => 'deleted book',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'updated bookshelf',
     'bookshelf_update_notification'    => 'Bookshelf successfully updated',
     'bookshelf_delete'                 => 'deleted bookshelf',
index ad0d516bb1d5e2f6a9d7006d422cf1ad9b910141..c670106f9b64d79f28c666e8122e077e6b0f355d 100644 (file)
@@ -38,6 +38,11 @@ return [
     '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.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // 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.',
index 2f09e53d1fe88389e923863d875c43e8d2713d4a..703a70c7e6aa5bea2b59f7319d4739c5f7162c13 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Previous',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Sort Options',
index bed781b6129b180789556b43597883ba5671da21..27d67487a0b0cb3aaffe6adb71c70d10f11c73e5 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 1b74e2a74d32a7a79736540e9cff52f48d81b65f..8ef584ed2504eed06ff3ba3e70e36d2e21d5d0aa 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'libro creado',
     'book_create_notification'    => 'Libro creado correctamente',
+    'book_create_from_chapter'              => 'convertido capítulo a libro',
+    'book_create_from_chapter_notification' => 'Capítulo convertido a libro con éxito',
     'book_update'                 => 'libro actualizado',
     'book_update_notification'    => 'Libro actualizado correctamente',
     'book_delete'                 => 'libro eliminado',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'estante creado',
     'bookshelf_create_notification'    => 'Estante creado correctamente',
+    'bookshelf_create_from_book'    => 'convertido libro a estante',
+    'bookshelf_create_from_book_notification'    => 'Libro convertido a estante con éxito',
     'bookshelf_update'                 => 'estante actualizado',
     'bookshelf_update_notification'    => 'Estante actualizado correctamente',
     'bookshelf_delete'                 => 'estante eliminado',
index f354321383955a9d23b22c425a83d7057c869556..093b7e02a0bd203eac03f8fe16fcdf21546d06c9 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Este dominio de correo electrónico no tiene acceso a esta aplicación',
     'register_success' => '¡Gracias por registrarse! Ahora se encuentra registrado y logueado.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Intentando iniciar sesión',
+    'auto_init_starting_desc' => 'Estamos contactando con su sistema de autenticación para comenzar el proceso de inicio de sesión. Si no hay progreso después de 5 segundos puede intentar hacer clic en el enlace de abajo.',
+    'auto_init_start_link' => 'Continuar con la autenticación',
+
     // Password Reset
     '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',
index 6320d340ac5efe8c25a5afe3d389769a5bece3b8..a58507bc62c6b0939f6059246151e386c8c15fab 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Anterior',
     'filter_active' => 'Filtro activo:',
     'filter_clear' => 'Limpiar filtro',
+    'download' => 'Descargar',
+    'open_in_tab' => 'Abrir en una nueva pestaña',
 
     // Sort Options
     'sort_options' => 'Opciones de ordenación',
index 1b579b36030fae96552b2117ba1df2c4e571cdff..5aa7eff1c0e49822424c658517003e9951eea4bf 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Los archivos de imagen de de las páginas no serán duplicados y las imágenes originales conservarán su relación con la página a la que fueron subidos originalmente.',
     'copy_consider_attachments' => 'Los archivos adjuntos de la página no serán copiados.',
     'copy_consider_access' => 'Un cambio de ubicación, propietario o permisos puede resultar en que este contenido sea accesible para aquellos que anteriormente no tuvieran acceso.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convertir a Estante',
+    'convert_to_shelf_contents_desc' => 'Puedes convertir este libro a un nuevo estante con el mismo contenido. Los capítulos contenidos en este libro se convertirán en libros nuevos. Si este libro contiene alguna página, que no esté en un capítulo, este libro será renombrado y contendrá tales páginas, y este libro pasará a formar parte del nuevo estante.',
+    'convert_to_shelf_permissions_desc' => 'Cualquier permiso establecido en este libro será copiado al nuevo estante y a todos los nuevos libros que no tengan sus propios permisos configurados. Tenga en cuenta que los permisos de los estantes no se aplican automáticamente sobre el contenido en su interior, como lo hacen para los libros.',
+    'convert_book' => 'Convertir Libro',
+    'convert_book_confirm' => '¿Está seguro de que desea borrar este libro?',
+    'convert_undo_warning' => 'Esto no puede revertirse de forma sencilla.',
+    'convert_to_book' => 'Convertir a Libro',
+    'convert_to_book_desc' => 'Puede convertir este capítulo en un nuevo libro con el mismo contenido. Cualquier permiso establecido en este capítulo será copiado al nuevo libro pero cualquier permiso heredado, del libro padre, no se copiará lo que podría conducir a un cambio de control de acceso.',
+    'convert_chapter' => 'Convertir Capítulo',
+    'convert_chapter_confirm' => '¿Estás seguro de que quieres convertir este capítulo?',
 ];
index 0602079b2bafefb8bca0351d653f2dc37449ef4d..aa761f6d226141f21fc377b89f179273ed893ec8 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'libro creado',
     'book_create_notification'    => 'Libro creado correctamente',
+    'book_create_from_chapter'              => 'convertido capítulo a libro',
+    'book_create_from_chapter_notification' => 'Capítulo convertido a libro con éxito',
     'book_update'                 => 'libro actualizado',
     'book_update_notification'    => 'Libro actualizado correctamente',
     'book_delete'                 => 'libro borrado',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'estante creado',
     'bookshelf_create_notification'    => 'Estante creado correctamente',
+    'bookshelf_create_from_book'    => 'convertido libro a estante',
+    'bookshelf_create_from_book_notification'    => 'Libro convertido a estante con éxito',
     'bookshelf_update'                 => 'Estante actualizado',
     'bookshelf_update_notification'    => 'Estante actualizado correctamente',
     'bookshelf_delete'                 => 'Estante borrado',
@@ -61,7 +65,7 @@ return [
 
     // Users
     'user_update_notification' => 'Usuario actualizado correctamente',
-    'user_delete_notification' => 'Usuario eliminado correctamente',
+    'user_delete_notification' => 'El usuario fue eliminado correctamente',
 
     // Other
     'commented_on'                => 'comentado',
index 3717063572fa89c8004523a9eed4dfc388898283..2351be129d8aa89db827b33af23943681c067b03 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Este dominio de correo electrónico no tiene acceso a esta aplicación',
     'register_success' => '¡Gracias por registrarse! Ahora se encuentra registrado y ha accedido a la aplicación.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Intentando iniciar sesión',
+    'auto_init_starting_desc' => 'Estamos contactando con su sistema de autenticación para comenzar el proceso de inicio de sesión. Si no hay progreso después de 5 segundos puede intentar hacer clic en el enlace de abajo.',
+    'auto_init_start_link' => 'Continuar con la autenticación',
+
     // Password Reset
     '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',
index 2b681f961c48b9faff9c918688e0f8ce8a58ea55..1ba494c50f11319be3ac7032a344fdf12c2c0e6d 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Anterior',
     'filter_active' => 'Filtro activo:',
     'filter_clear' => 'Limpiar filtro',
+    'download' => 'Descargar',
+    'open_in_tab' => 'Abrir en una nueva pestaña',
 
     // Sort Options
     'sort_options' => 'Opciones de Orden',
index 9ffa354d00f4e627c32d70d2305e50d7ce1d26fb..fa37e121b76e61b24885b7ca31fa149c9f361188 100644 (file)
@@ -204,9 +204,9 @@ return [
     'pages_edit_enter_changelog_desc' => 'Introduzca una breve descripción de los cambios que ha realizado',
     'pages_edit_enter_changelog' => 'Entrar en cambio de registro',
     'pages_editor_switch_title' => 'Cambiar editor',
-    'pages_editor_switch_are_you_sure' => '¿Está seguro de que desea cambiar el editor de esta página?',
-    'pages_editor_switch_consider_following' => 'Considere lo siguiente al cambiar de editor:',
-    'pages_editor_switch_consideration_a' => 'Una vez guardado, el nuevo editor será utilizado por cualquier usuario en el futuro, incluyendo aquellos que no puedan cambiar el tipo de editor por sí mismos.',
+    'pages_editor_switch_are_you_sure' => '¿Está seguro de que desea cambiar el editor en esta página?',
+    'pages_editor_switch_consider_following' => 'Considere lo siguiente cuando cambie de editor:',
+    'pages_editor_switch_consideration_a' => 'Una vez guardado, el nuevo editor será utilizado por todos los usuarios nuevos, incluyendo aquellos que quizás no tengan permisos para cambiar su editor.',
     'pages_editor_switch_consideration_b' => 'Esto puede llevar a una pérdida de detalle y sintaxis en ciertas circunstancias.',
     'pages_editor_switch_consideration_c' => 'Cambios en etiquetas o en el registro de cambios, realizados desde el último guardado, no persistirán a través de este cambio.',
     'pages_save' => 'Guardar página',
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Los archivos de imagen de la página no serán duplicados y las imágenes originales conservarán su relación con la página a la que fueron subidos originalmente.',
     'copy_consider_attachments' => 'Los archivos adjuntos de la página no serán copiados.',
     'copy_consider_access' => 'Un cambio de ubicación, propietario o permisos puede resultar en que este contenido sea accesible para aquellos que anteriormente no tuvieran acceso.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convertir a Estante',
+    'convert_to_shelf_contents_desc' => 'Puedes convertir este libro a un nuevo estante con el mismo contenido. Los capítulos contenidos en este libro se convertirán en libros nuevos. Si este libro contiene alguna página, que no esté en un capítulo, este libro será renombrado y contendrá tales páginas, y este libro pasará a formar parte del nuevo estante.',
+    'convert_to_shelf_permissions_desc' => 'Cualquier permiso establecido en este libro será copiado al nuevo estante y a todos los nuevos libros que no tengan sus propios permisos configurados. Tenga en cuenta que los permisos de los estantes no se aplican automáticamente sobre el contenido en su interior, como lo hacen para los libros.',
+    'convert_book' => 'Convertir Libro',
+    'convert_book_confirm' => '¿Está seguro de que desea borrar este libro?',
+    'convert_undo_warning' => 'Esto no puede revertirse de forma sencilla.',
+    'convert_to_book' => 'Convertir a Libro',
+    'convert_to_book_desc' => 'Puede convertir este capítulo en un nuevo libro con el mismo contenido. Cualquier permiso establecido en este capítulo será copiado al nuevo libro pero cualquier permiso heredado, del libro padre, no se copiará lo que podría conducir a un cambio de control de acceso.',
+    'convert_chapter' => 'Convertir Capítulo',
+    'convert_chapter_confirm' => '¿Estás seguro de que quieres convertir este capítulo?',
 ];
index 5f65d0a6dd5dac8216ae364726860f8d7a5e7adf..43c08054343e829fe576cee9b8113cb922225663 100644 (file)
@@ -28,7 +28,7 @@ return [
     'app_secure_images_toggle' => 'Habilitar seguridad alta para subir imágenes',
     'app_secure_images_desc' => 'Por razones de rendimiento, todas las imágenes son públicas. Esta opción agrega una cadena larga difícil de adivinar, asegúrese que los índices de directorios no están habilitados para prevenir el acceso fácil a las imágenes.',
     'app_default_editor' => 'Editor de Página por defecto',
-    'app_default_editor_desc' => 'Seleccione qué editor se utilizará por defecto cuando se editen nuevas páginas. Esto se puede anular a nivel de página si los permisos lo permiten.',
+    'app_default_editor_desc' => 'Seleccione qué editor se utilizará por defecto cuando se editen nuevas páginas. Esta acción se puede anular al nivel de página si los permisos lo permiten.',
     'app_custom_html' => 'Contenido de cabecera HTML personalizable',
     'app_custom_html_desc' => 'Cualquier contenido agregado aquí será agregado al final de la sección <head> de cada página. Esto es útil para sobreescribir estilos o agregar código para analíticas.',
     'app_custom_html_disabled_notice' => 'El contenido personailzado para la cabecera HTML está deshabilitado en esta configuración para garantizar que cualquier cambio importante se pueda revertir.',
index ffcf37b2dfd1ffc020534395f29dc97ec56c3756..26e4e5ac04aa798d50f1384bf917b2f2dffee587 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'lisas raamatu',
     'book_create_notification'    => 'Raamat on lisatud',
+    'book_create_from_chapter'              => 'muutis peatüki raamatuks',
+    'book_create_from_chapter_notification' => 'Peatükk on muudetud raamatuks',
     'book_update'                 => 'muutis raamatut',
     'book_update_notification'    => 'Raamat on muudetud',
     'book_delete'                 => 'kustutas raamatu',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'lisas riiuli',
     'bookshelf_create_notification'    => 'Riiul on lisatud',
+    'bookshelf_create_from_book'    => 'muutis raamatu riiuliks',
+    'bookshelf_create_from_book_notification'    => 'Raamat on muudetud riiuliks',
     'bookshelf_update'                 => 'muutis riiulit',
     'bookshelf_update_notification'    => 'Riiul on muudetud',
     'bookshelf_delete'                 => 'kustutas riiuli',
index 7a1817cb7e2359672f7d5eb01ee4301bb2704790..b8fb471a8224e4a55e69b42ae84b12043b592bb6 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Sellel e-posti domeenil ei ole rakendusele ligipääsu',
     'register_success' => 'Aitäh, et registreerusid! Oled nüüd sisse logitud.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Sisselogimiskatse',
+    'auto_init_starting_desc' => 'Sisselogimise protsessi alustamiseks autentimissüsteemiga ühendumine. Kui 5 sekundi jooksul edasiminekut ei ole, proovi alloleval lingil klikkida.',
+    'auto_init_start_link' => 'Jätka autentimisega',
+
     // Password Reset
     'reset_password' => 'Lähtesta parool',
     'reset_password_send_instructions' => 'Siseta oma e-posti aadress ning sulle saadetakse link parooli lähtestamiseks.',
index 320c55ee220d27d67e12eb536e17f6b1df4a8c3b..f0a0811527df4eeff29b31ad5dc994aef27c6e6f 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Eelmine',
     'filter_active' => 'Aktiivne filter:',
     'filter_clear' => 'Tühjenda filter',
+    'download' => 'Laadi alla',
+    'open_in_tab' => 'Ava vahelehel',
 
     // Sort Options
     'sort_options' => 'Sorteerimise valikud',
index 009a3d562bb690ab0a30e45d473ac353649492bd..ae49d2d293d1ef43fdd6895e1cef6a8d0887b09c 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Lehel olevaid pildifaile ei dubleerita. Pildid säilitavad viite lehele, millele nad algselt lisati.',
     'copy_consider_attachments' => 'Lehe manuseid ei kopeerita.',
     'copy_consider_access' => 'Asukoha, omaniku või õiguste muudatused võivad teha sisu kättesaadavaks neile, kellel varem sellele ligipääs puudus.',
+
+    // Conversions
+    'convert_to_shelf' => 'Muuda riiuliks',
+    'convert_to_shelf_contents_desc' => 'Saad muuta selle raamatu uueks, sama sisuga riiuliks. Raamatu peatükid muudetakse uuteks raamatuteks. Kui raamat sisaldab lehti, mis ei kuulu ühegi peatüki alla, nimetatakse see raamat ümber ning see saab uue riiuli osana sisaldama neid lehti.',
+    'convert_to_shelf_permissions_desc' => 'Raamatule määratud õigused kopeeritakse uuele riiulile ja kõigile uutele raamatutele, millel ei ole endal määratud õiguseid. Pane tähele, et riiulitele määratud õigused ei rakendu automaatselt sisule, nagu raamatute puhul.',
+    'convert_book' => 'Muuda raamat',
+    'convert_book_confirm' => 'Kas oled kindel, et soovid selle raamatu muuta?',
+    'convert_undo_warning' => 'Seda ei saa lihtsasti tagasi võtta.',
+    'convert_to_book' => 'Muuda raamatuks',
+    'convert_to_book_desc' => 'Saad muuta selle peatüki uueks, sama sisuga raamatuks. Peatükile määratud õigused kopeeritakse uuele raamatule, aga olemasolevalt raamatult pärit õiguseid ei kopeerita, mis võib põhjustada muudatusi ligipääsudes.',
+    'convert_chapter' => 'Muud peatükk',
+    'convert_chapter_confirm' => 'Kas oled kindel, et soovid selle peatüki muuta?',
 ];
index 6847488a8f193d185f8ada29e3f5e13118db9256..3f1676a9ee10286f54f1fb80f89201fdb212352c 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'liburua sortuta',
     'book_create_notification'    => 'Liburua ongi sortu da',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'liburua eguneratuta',
     'book_update_notification'    => 'Liburua egoki eguneratua',
     'book_delete'                 => 'liburua ezabatua',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'apalategia sortuta',
     'bookshelf_create_notification'    => 'Apalategia egoki sortuta',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'apalategia eguneratuta',
     'bookshelf_update_notification'    => 'Apalategia egoki eguneratuta',
     'bookshelf_delete'                 => 'apalategia ezabatua',
index a9ac47dbddc8e4f09fbf5ceb5502cdb5d307bbf4..0ef81239cc6b69b8db867d51f5e08e25c480edbe 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Posta elektronikoko domeinu hori ez dago eskuragarri aplikazio honetarako',
     'register_success' => 'Eskerrik asko izen emateagatik! Orain izena emanda eta saioa hasita zaude.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Pasahitza berrezarri',
     'reset_password_send_instructions' => 'Sartu zure posta elektronikoa eta posta elektroniko bat bidaliko dizute pasahitza berritzeko esteka batekin.',
index 013afd68008f7f7229d98080b0e38c8b3c72755f..9ad8e8b796aa01209ba20cc3103512441d4bc9b6 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Aurrekoa',
     'filter_active' => 'Iragazki aktiboa:',
     'filter_clear' => 'Iragazkia garbitu',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Ordenatzeko aukerak',
index 6c71e0c5bd48d995ca1df9b03a4e4d8345b456c5..87a55e368e00f3f44eafe03cdf1cd704889ce49d 100644 (file)
@@ -158,29 +158,29 @@ return [
     'chapters_delete_explain' => 'This will delete the chapter with the name \':chapterName\'. All pages that exist within this chapter will also be deleted.',
     'chapters_delete_confirm' => 'Ziur kapitulu hau ezabatu nahi duzula?',
     'chapters_edit' => 'Kapitulua aldatu',
-    'chapters_edit_named' => 'Edit Chapter :chapterName',
+    'chapters_edit_named' => ':chapterName kapitulua editatu',
     'chapters_save' => 'Kapitulua gorde',
     'chapters_move' => 'Kapitulua mugitu',
-    'chapters_move_named' => 'Move Chapter :chapterName',
-    'chapter_move_success' => 'Chapter moved to :bookName',
+    'chapters_move_named' => ':chapterName kapitulua mugitu',
+    'chapter_move_success' => ':bookName liburura mugitu da kapitulua',
     'chapters_copy' => 'Kapitulua kopiatu',
     'chapters_copy_success' => 'Kapitulua egoki kopiatua',
-    'chapters_permissions' => 'Chapter Permissions',
+    'chapters_permissions' => 'Kapitulu baimenak',
     'chapters_empty' => 'Ez dago orrialderik kapitulu honetan.',
-    'chapters_permissions_active' => 'Chapter Permissions Active',
-    'chapters_permissions_success' => 'Chapter Permissions Updated',
-    'chapters_search_this' => 'Search this chapter',
+    'chapters_permissions_active' => 'Liburu baimenak altan',
+    'chapters_permissions_success' => 'Liburu baimenak eguneratuta',
+    'chapters_search_this' => 'Kapitulu hau bilatu',
 
     // Pages
     'page' => 'Orria',
     'pages' => 'Orriak',
-    'x_pages' => ':count Page|:count Pages',
+    'x_pages' => 'orrialde:count|:count orrialde',
     'pages_popular' => 'Orrialde ikusienak',
     'pages_new' => 'Orrialde berria',
     'pages_attachments' => 'Eranskinak',
     'pages_navigation' => 'Nabigazio orrialdea',
     'pages_delete' => 'Ezabatu orria',
-    'pages_delete_named' => 'Delete Page :pageName',
+    'pages_delete_named' => ':pageName Orria ezabatu',
     'pages_delete_draft_named' => 'Delete Draft Page :pageName',
     'pages_delete_draft' => 'Delete Draft Page',
     'pages_delete_success' => 'Orria ezabatua',
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index c1211e92fd9076d21a1d940614a5ccd791e284f5..d958604b401c5419000ee48c404d41c0a2773fe2 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'ایجاد کتاب',
     'book_create_notification'    => 'کتاب با موفقیت ایجاد شد',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'به روزرسانی کتاب',
     'book_update_notification'    => 'کتاب با موفقیت به روزرسانی شد',
     'book_delete'                 => 'حذف کتاب',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'ایجاد قفسه کتاب',
     'bookshelf_create_notification'    => 'قفسه کتاب با موفقیت ایجاد شد',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'به روزرسانی قفسه کتاب',
     'bookshelf_update_notification'    => 'قفسه کتاب با موفقیت به روزرسانی شد',
     'bookshelf_delete'                 => 'حذف قفسه کتاب',
index 9555f9a08ba33ca24afbfe4f89defca7d6504201..ef444e4f3b9b9a48c02beddc87b9039e739c7e61 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'دامنه پست الکترونیک به این برنامه دسترسی ندارد',
     'register_success' => 'از ثبت نام شما سپاسگزاریم! شما اکنون ثبت نام کرده و وارد سیستم شده اید.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'بازنشانی کلمه عبور',
     'reset_password_send_instructions' => 'پست الکترونیک خود را در کادر زیر وارد نموده تا یک پیام حاوی لینک بازنشانی کلمه عبور دریافت نمایید.',
index 8dbe8d7c807c1f9b578f1aae82844b92ae28fce2..0203c7734bad59e7a8b24fe2cec35917e0a80202 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'قبلى',
     'filter_active' => 'فیلتر فعال:',
     'filter_clear' => 'پاک کردن فیلتر',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'گزینه‌های مرتب سازی',
index eb6115468ed746e9718f538cca443d493ff011c0..5ca3b4180d9cb58d428b6603abf4811fb1a2d872 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'فایل های تصویر صفحه تکراری نخواهند شد و تصاویر اصلی ارتباط خود را با صفحه ای که در ابتدا در آن آپلود شده اند حفظ می کنند.',
     'copy_consider_attachments' => 'پیوست های صفحه کپی نمی شود.',
     'copy_consider_access' => 'تغییر مکان، مالک یا مجوزها ممکن است منجر به دسترسی به این محتوا برای افرادی شود که قبلاً به آنها دسترسی نداشتند.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 6ca8f2e9314349792140b614ab91057a558e4d11..d0386f5940444de72668d1de4a08d9ff3ada10f1 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'a créé un livre',
     'book_create_notification'    => 'Livre créé avec succès',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'a modifié le livre',
     'book_update_notification'    => 'Livre modifié avec succès',
     'book_delete'                 => 'a supprimé un livre',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'a créé l\'étagère',
     'bookshelf_create_notification'    => 'Étagère créée avec succès',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'a modifié l\'étagère',
     'bookshelf_update_notification'    => 'Étagère modifiée avec succès',
     'bookshelf_delete'                 => 'a supprimé l\'étagère',
index 0057948eb0e9be6b8a1d1fe7588565c82bfd8b9c..741b5eaaa9c3ff02acedcda9b076baca6b8a6088 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Cette adresse e-mail ne peut pas accéder à l\'application',
     'register_success' => 'Merci pour votre inscription. Vous êtes maintenant inscrit(e) et connecté(e)',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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é.',
index 1df172dc3c0c7903c41a6fceb3276de389b55ad2..1256f16e3ef48a2e94990b2f7eb858e6571f997e 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Précédent',
     'filter_active' => 'Filtre actif :',
     'filter_clear' => 'Effacer le filtre',
+    'download' => 'Télécharger',
+    'open_in_tab' => 'Ouvrir dans un onglet',
 
     // Sort Options
     'sort_options' => 'Options de tri',
index 0ca7b126ab1feb29f578e94630ed5ce53fd51e1a..2e448c609a7a784066f86265b960b2c59528a3a2 100644 (file)
@@ -24,7 +24,7 @@ return [
     'width' => 'Largeur',
     'height' => 'Hauteur',
     'More' => 'Plus',
-    'select' => 'Select...',
+    'select' => 'Sélectionner...',
 
     // Toolbar
     'formats' => 'Formats',
@@ -53,14 +53,14 @@ return [
     'align_left' => 'Aligner à gauche',
     'align_center' => 'Aligner au centre',
     'align_right' => 'Aligner à droite',
-    'align_justify' => 'Justify',
+    'align_justify' => 'Justifier',
     'list_bullet' => 'Liste à puces',
     'list_numbered' => 'Liste numérotée',
-    'list_task' => 'Task list',
+    'list_task' => 'Liste de tâches',
     'indent_increase' => 'Augmenter l\'indentation',
     'indent_decrease' => 'Diminuer l\'indentation',
     'table' => 'Tableau',
-    'insert_image' => 'Inserer une image',
+    'insert_image' => 'Insérer une image',
     'insert_image_title' => 'Insérer/Modifier une image',
     'insert_link' => 'Insérer/modifier un lien',
     'insert_link_title' => 'Insérer/Modifier un lien',
@@ -93,10 +93,10 @@ return [
     'cell_properties_title' => 'Propriétés de la cellule',
     'cell_type' => 'Type de cellule',
     'cell_type_cell' => 'Cellule',
-    'cell_scope' => 'Scope',
+    'cell_scope' => 'Champ',
     'cell_type_header' => 'Cellule d\'en-tête',
-    'merge_cells' => 'Merge cells',
-    'split_cell' => 'Split cell',
+    'merge_cells' => 'Fusionner les cellules',
+    'split_cell' => 'Scinder la cellule',
     'table_row_group' => 'Groupe de ligne',
     'table_column_group' => 'Groupe de colonnes',
     'horizontal_align' => 'Aligner horizontalement',
@@ -124,22 +124,22 @@ return [
     'caption' => 'Légende',
     'show_caption' => 'Afficher la légende',
     'constrain' => 'Conserver les proportions',
-    'cell_border_solid' => 'Solid',
-    'cell_border_dotted' => 'Dotted',
-    'cell_border_dashed' => 'Dashed',
-    'cell_border_double' => 'Double',
-    'cell_border_groove' => 'Groove',
-    'cell_border_ridge' => 'Ridge',
-    'cell_border_inset' => 'Inset',
-    'cell_border_outset' => 'Outset',
-    'cell_border_none' => 'None',
-    'cell_border_hidden' => 'Hidden',
+    'cell_border_solid' => 'En continue',
+    'cell_border_dotted' => 'En pointillé',
+    'cell_border_dashed' => 'En tirets',
+    'cell_border_double' => 'En double trait',
+    'cell_border_groove' => 'En creux',
+    'cell_border_ridge' => 'En saillie',
+    'cell_border_inset' => 'En 3d lumière basse',
+    'cell_border_outset' => 'En 3d lumière haute',
+    'cell_border_none' => 'Aucun',
+    'cell_border_hidden' => 'Masquée',
 
     // Images, links, details/summary & embed
     'source' => 'Source',
     'alt_desc' => 'Description alternative',
     'embed' => 'Intégrer',
-    'paste_embed' => 'Collez votre code intégré ci-dessous:',
+    'paste_embed' => 'Collez votre code intégré ci-dessous :',
     'url' => 'URL',
     'text_to_display' => 'Texte à afficher',
     'title' => 'Titre',
@@ -154,14 +154,14 @@ return [
     'toggle_label' => 'Activer/désactiver le libellé',
 
     // About view
-    'about' => 'About the editor',
+    'about' => 'À propos de l\'éditeur',
     'about_title' => 'À propos de l\'éditeur WYSIWYG',
     'editor_license' => 'Licence d\'éditeur et droit d\'auteur',
-    'editor_tiny_license' => 'Cet éditeur est construit en utilisant :tinyLink qui est fourni sous une licence LGPL v2.1.',
+    'editor_tiny_license' => 'Cet éditeur est construit en utilisant :tinyLink qui est fourni sous licence LGPL v2.1.',
     'editor_tiny_license_link' => 'Vous trouverez ici les détails sur les droits d\'auteur et les licences de TinyMCE.',
     'save_continue' => 'Enregistrer et continuer',
     'callouts_cycle' => '(Continuez d\'appuyer pour basculer entre les types)',
-    'link_selector' => 'Link to content',
+    'link_selector' => 'Lien vers le contenu',
     'shortcuts' => 'Raccourcis',
     'shortcut' => 'Raccourci',
     'shortcuts_intro' => 'Les raccourcis suivants sont disponibles dans l\'éditeur :',
index 9537c09664fe57efda0e52251c523867123b6ada..963f6569d529400547fa70da2931fe018649abd3 100644 (file)
@@ -156,7 +156,7 @@ return [
     'chapters_delete' => 'Supprimer le chapitre',
     'chapters_delete_named' => 'Supprimer le chapitre :chapterName',
     'chapters_delete_explain' => 'Ceci supprimera le chapitre portant le nom \':chapterName\'. Toutes les pages qui existent dans ce chapitre seront également supprimées.',
-    'chapters_delete_confirm' => 'Etes-vous sûr(e) de vouloir supprimer ce chapitre ?',
+    'chapters_delete_confirm' => 'Êtes-vous sûr(e) de vouloir supprimer ce chapitre ?',
     'chapters_edit' => 'Modifier le chapitre',
     'chapters_edit_named' => 'Modifier le chapitre :chapterName',
     'chapters_save' => 'Enregistrer le chapitre',
@@ -196,19 +196,19 @@ return [
     'pages_edit_draft_save_at' => 'Brouillon enregistré le ',
     'pages_edit_delete_draft' => 'Supprimer le brouillon',
     'pages_edit_discard_draft' => 'Jeter le brouillon',
-    'pages_edit_switch_to_markdown' => 'Switch to Markdown Editor',
-    'pages_edit_switch_to_markdown_clean' => '(Clean Content)',
-    'pages_edit_switch_to_markdown_stable' => '(Stable Content)',
-    'pages_edit_switch_to_wysiwyg' => 'Switch to WYSIWYG Editor',
+    'pages_edit_switch_to_markdown' => 'Basculer vers l\'éditeur Markdown',
+    'pages_edit_switch_to_markdown_clean' => '(Contenu nettoyé)',
+    'pages_edit_switch_to_markdown_stable' => '(Contenu stable)',
+    'pages_edit_switch_to_wysiwyg' => 'Basculer vers l\'éditeur WYSIWYG',
     'pages_edit_set_changelog' => 'Remplir le journal des changements',
     'pages_edit_enter_changelog_desc' => 'Entrez une brève description des changements effectués',
     'pages_edit_enter_changelog' => 'Ouvrir le journal des changements',
-    'pages_editor_switch_title' => 'Switch Editor',
-    'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?',
-    'pages_editor_switch_consider_following' => 'Consider the following when changing editors:',
-    'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.',
-    'pages_editor_switch_consideration_b' => 'This can potentially lead to a loss of detail and syntax in certain circumstances.',
-    'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.',
+    'pages_editor_switch_title' => 'Changer d\'éditeur',
+    'pages_editor_switch_are_you_sure' => 'Êtes-vous sûr de vouloir modifier l\'éditeur de cette page ?',
+    'pages_editor_switch_consider_following' => 'Considérez ce qui suit lors du changement d\'éditeur :',
+    'pages_editor_switch_consideration_a' => 'Une fois enregistrée, le nouvel éditeur sera utilisé par tous les futurs éditeurs, y compris ceux qui ne seront pas en mesure de modifier le type de l\'éditeur eux-mêmes.',
+    'pages_editor_switch_consideration_b' => 'Cela peut entraîner une perte de détail et de syntaxe dans certaines circonstances.',
+    'pages_editor_switch_consideration_c' => 'Les modifications apportées depuis la dernière sauvegarde, les balises ou le journal des modifications ne persisteront pas à travers cette modification.',
     'pages_save' => 'Enregistrer la page',
     'pages_title' => 'Titre de la page',
     'pages_name' => 'Nom de la page',
@@ -235,7 +235,7 @@ return [
     'pages_revisions_number' => '#',
     'pages_revisions_numbered' => 'Révision #:id',
     'pages_revisions_numbered_changes' => 'Modification #:id',
-    'pages_revisions_editor' => 'Editor Type',
+    'pages_revisions_editor' => 'Type d\'éditeur',
     'pages_revisions_changelog' => 'Journal des changements',
     'pages_revisions_changes' => 'Changements',
     'pages_revisions_current' => 'Version actuelle',
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Les fichiers image de la page ne seront pas dupliqués et les images originales conserveront leur relation avec la page vers laquelle elles ont été initialement téléchargées.',
     'copy_consider_attachments' => 'Les pièces jointes de la page ne seront pas copiées.',
     'copy_consider_access' => 'Un changement d\'emplacement, de propriétaire ou d\'autorisation peut rendre ce contenu accessible à ceux précédemment sans accès.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index f8858d692f57e9ff39ce0074cf12eec7d8ae222a..ffa577c1e0fcc35364d73c3e67563071935d6b90 100644 (file)
@@ -10,8 +10,8 @@ return [
     'settings' => 'Préférences',
     'settings_save' => 'Enregistrer les préférences',
     'settings_save_success' => 'Préférences enregistrées',
-    'system_version' => 'System Version',
-    'categories' => 'Categories',
+    'system_version' => 'Version du système',
+    'categories' => 'Catégories',
 
     // App Settings
     'app_customization' => 'Personnalisation',
@@ -27,8 +27,8 @@ return [
     'app_secure_images' => 'Ajout d\'image sécurisé',
     'app_secure_images_toggle' => 'Activer l\'ajout d\'image sécurisé',
     'app_secure_images_desc' => 'Pour des questions de performances, toutes les images sont publiques. Cette option ajoute une chaîne aléatoire difficile à deviner dans les URLs des images.',
-    'app_default_editor' => 'Default Page Editor',
-    'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.',
+    'app_default_editor' => 'Éditeur de page par défaut',
+    'app_default_editor_desc' => 'Sélectionnez l\'éditeur qui sera utilisé par défaut lors de l\'édition de nouvelles pages. Cela peut être remplacé au niveau de la page où les permissions sont autorisées.',
     'app_custom_html' => 'HTML personnalisé dans l\'en-tête',
     'app_custom_html_desc' => 'Le contenu inséré ici sera ajouté en bas de la balise <head> de toutes les pages. Vous pouvez l\'utiliser pour ajouter du CSS personnalisé ou un tracker analytique.',
     'app_custom_html_disabled_notice' => 'Le contenu de l\'en-tête HTML personnalisé est désactivé sur cette page de paramètres pour garantir que les modifications les plus récentes puissent être annulées.',
@@ -152,7 +152,7 @@ return [
     'role_access_api' => 'Accès à l\'API du système',
     'role_manage_settings' => 'Gérer les préférences de l\'application',
     'role_export_content' => 'Exporter le contenu',
-    'role_editor_change' => 'Change page editor',
+    'role_editor_change' => 'Changer l\'éditeur de page',
     'role_asset' => 'Permissions des ressources',
     'roles_system_warning' => 'Sachez que l\'accès à l\'une des trois permissions ci-dessus peut permettre à un utilisateur de modifier ses propres privilèges ou les privilèges des autres utilisateurs du système. N\'attribuez uniquement des rôles avec ces permissions qu\'à des utilisateurs de confiance.',
     'role_asset_desc' => 'Ces permissions contrôlent l\'accès par défaut des ressources dans le système. Les permissions dans les livres, les chapitres et les pages ignoreront ces permissions',
@@ -254,7 +254,7 @@ return [
     'webhooks_delete' => 'Supprimer le Webhook',
     'webhooks_delete_warning' => 'Ceci supprimera complètement du système le webhook ayant le nom \':webhookName\'.',
     'webhooks_delete_confirm' => 'Êtes-vous sûr(e) de vouloir supprimer ce webhook ?',
-    'webhooks_format_example' => 'Exemple de Format de Webhook',
+    'webhooks_format_example' => 'Exemple de format de webhook',
     'webhooks_format_example_desc' => 'Les données du webhook sont envoyées dans une requête POST vers l\'endpoint au format JSON respectant le format ci-dessous. Les propriétés "related_item" et "url" sont optionnelles et dépendront du type d\'événement déclenché.',
     'webhooks_status' => 'Statut du webhook',
     'webhooks_last_called' => 'Dernier appel :',
index ede04a86ceb2ce281a7d847757be0c2dd4e5db00..4df8a981705f856763de484ae3320a82d1ab75a4 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'ספר נוצר',
     'book_create_notification'    => 'ספר נוצר בהצלחה',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'ספר הועדכן',
     'book_update_notification'    => 'ספר התעדכן בהצלחה',
     'book_delete'                 => 'ספר נמחק',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'updated bookshelf',
     'bookshelf_update_notification'    => 'Bookshelf successfully updated',
     'bookshelf_delete'                 => 'deleted bookshelf',
index 9d50dead7ab50af050384e0a5821c8849362875c..3c42ecef231297cbf84b2bc586b18543fb02317d 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'לא ניתן להרשם באמצעות המייל שסופק',
     'register_success' => 'תודה על הרשמתך! ניתן כעת להתחבר',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'איפוס סיסמא',
     'reset_password_send_instructions' => 'יש להזין את כתובת המייל למטה ואנו נשלח אלייך הוראות לאיפוס הסיסמא',
index 865a224de34f156c99fb9ebc9e0799e0cd01c10d..512bcf6c3ce7e2883b78094e6e1c57706a7def00 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'קודם',
     'filter_active' => 'מסנן פעיל:',
     'filter_clear' => 'נקה מסננים',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'אפשרויות מיון',
index ad49c895fee69d756586bc35ae2db0dcfa3f36b0..f3fcb86882a52f9e54d31afa35544f7a21462c7b 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 0d467ea8fdf6f4ab21bfc5f5aae7167f510f7d88..79f4af04e6be5437de2c1ddbd112d24e4a144ff3 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'stvorena knjiga',
     'book_create_notification'    => 'Book successfully created',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'ažurirana knjiga',
     'book_update_notification'    => 'Book successfully updated',
     'book_delete'                 => 'izbrisana knjiga',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'ažurirana polica za knjige',
     'bookshelf_update_notification'    => 'Bookshelf successfully updated',
     'bookshelf_delete'                 => 'izbrisana polica za knjige',
index aff8ea4f6e5a9bfebba681fc308ad1500e13fa1c..bbaf9dede8bc8cc6d0925dc5c93281ffa45b6fac 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Ova e-mail adresa se ne može koristiti u ovoj aplikaciji',
     'register_success' => 'Hvala na prijavi! Sada ste registrirani i prijavljeni.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Promijenite lozinku',
     'reset_password_send_instructions' => 'Upišite svoju e-mail adresu kako biste primili poveznicu za promjenu lozinke.',
index 5e4a8f45135ec50b47f146bb5d61ab113ae12bde..ab2d36f3ff720611c643696e8b9df592101c7ee9 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Previous',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Razvrstaj opcije',
index e5e57b22b7b751aa8e83c2b9be5569498c06692c..f85dbc6cfac9d060872b9cf8a6874cea5d3f5f5b 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 04a3ac0ea8340b89fa22e234f783566b7514bc84..72e9ad07808f7aad1faae399d400c132b2752c86 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'létrehozott egy könyvet:',
     'book_create_notification'    => 'Könyv sikeresen létrehozva',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'frissítette a könyvet:',
     'book_update_notification'    => 'Könyv sikeresen frissítve',
     'book_delete'                 => 'törölte a könyvet:',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Könyvespolc sikeresen létrehozva',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'frissítette a könyvespolcot:',
     'bookshelf_update_notification'    => 'Könyvespolc sikeresen frissítve',
     'bookshelf_delete'                 => 'törölte a könyvespolcot:',
index 64e6ba2d3c5006d82a87d9ce18dde981590b5f49..6eafdd56583793a65c1590d29ba64bbe1d3628c1 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Ebből az email tartományról nem lehet hozzáférni ehhez az alkalmazáshoz',
     'register_success' => 'Köszönjük a regisztrációt! A regisztráció és a bejelentkezés megtörtént.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
index 7876a698c31cd9e4108723592b4193717a661002..156844d9f53882e6e387eb7d98335e3122a1b83f 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Előző',
     'filter_active' => 'Aktív szűrő:',
     'filter_clear' => 'Szűrő törlése',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Rendezési beállítások',
index 58b44076f08d3bb4cf2ebd5167b3e026a4b96096..795c642a9d5b5b92e85b5581c6314c8c3befcc18 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 2a2d35bd6192ee376e3fb2788d65fb76245ed6c8..e7b065c8a8b5071e1ef898b1b5e757c53c63cb01 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'membuat buku',
     'book_create_notification'    => 'Book successfully created',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'update buku',
     'book_update_notification'    => 'Book successfully updated',
     'book_delete'                 => 'hapus buku',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'update rak',
     'bookshelf_update_notification'    => 'Bookshelf successfully updated',
     'bookshelf_delete'                 => 'hapus rak buku',
index d76a05a01be4979548f9cb4e818fc56184623c34..694d6754fb26a9c49028561ff29a95fa4483c8a4 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Domain email tersebut tidak memiliki akses ke aplikasi ini',
     'register_success' => 'Terima kasih telah mendaftar! Anda sekarang terdaftar dan masuk.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Atur ulang kata sandi',
     'reset_password_send_instructions' => 'Masukkan email Anda di bawah ini dan Anda akan dikirimi email dengan tautan pengaturan ulang kata sandi.',
index b6c1f8d75a257e2f4449690b117eb1322a5980c1..8554e088eb4c555c0ff7656d9aa8de551523953d 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Sebelumnya',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Opsi Sortir',
index 65a9c4149d5755af8cd12fd77aa4e9d016df756f..b3e860b82547a18256d6b74e7f5fee3ad11ad8d4 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 27df10003efc0d5ac5633882f74df2466146e2db..b4c3db3c4cb9ee37f0a247806da177a0de35d0f0 100755 (executable)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'ha creato il libro',
     'book_create_notification'    => 'Libro creato con successo',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'ha aggiornato il libro',
     'book_update_notification'    => 'Libro aggiornato con successo',
     'book_delete'                 => 'ha eliminato il libro',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'libreria creata',
     'bookshelf_create_notification'    => 'Libreria creata con successo',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'ha aggiornato la libreria',
     'bookshelf_update_notification'    => 'Libreria aggiornata con successo',
     'bookshelf_delete'                 => 'ha eliminato la libreria',
index 3940b1ba197d8193d808e7de207d85f9bebf45e3..fdb169b377dcea2325757d61e7fade1bed73cda9 100755 (executable)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Questo dominio della mail non ha accesso a questa applicazione',
     'register_success' => 'Grazie per la registrazione! Sei registrato e loggato.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
index 36f5755edda78c485ceea840c1ec4066159db3e6..b97016403549a584b0631ba28d69df9313dac06c 100755 (executable)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Precedente',
     'filter_active' => 'Filtro attivo:',
     'filter_clear' => 'Pulisci filtro',
+    'download' => 'Download',
+    'open_in_tab' => 'Apri nella scheda',
 
     // Sort Options
     'sort_options' => 'Opzioni Ordinamento',
index e37777928dc60c13643d82f78688d531e3c71e17..dbe9103c1c36f8ba8820af0bf6074e8d56957f29 100755 (executable)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'I file delle immagini delle pagine non saranno duplicati e le immagini originali manterranno la loro relazione con la pagina su cui sono state originariamente caricate.',
     'copy_consider_attachments' => 'Gli allegati della pagina non saranno copiati.',
     'copy_consider_access' => 'Un cambiamento di luogo, di proprietario o di autorizzazioni può far sì che questo contenuto sia accessibile a chi prima non aveva accesso.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 45eaa3287970fc67d69efa3706bf6989e18fb1f8..6a470a750ebff0fd96ebeebd9bf9d14bd298cf9e 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'がブックを作成:',
     'book_create_notification'    => 'ブックを作成しました',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'がブックを更新:',
     'book_update_notification'    => 'ブックを更新しました',
     'book_delete'                 => 'がブックを削除:',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'が本棚を作成:',
     'bookshelf_create_notification'    => '本棚を作成しました',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'が本棚を更新:',
     'bookshelf_update_notification'    => '本棚を更新しました',
     'bookshelf_delete'                 => 'が本棚を削除:',
index 9c8d36669be4ff97611b5ed7727792996a892e02..b14432828a7fa4be831b4d1402238cb55d3435cc 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'このEmailドメインでの登録は許可されていません。',
     'register_success' => '登録が完了し、ログインできるようになりました!',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'パスワードリセット',
     'reset_password_send_instructions' => '以下にEメールアドレスを入力すると、パスワードリセットリンクが記載されたメールが送信されます。',
index 7c6cc1f59519f407fd141464c5cf40a03c8694e9..6ac4a2bf13c49518398c111b588b5a2efd6a29c1 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => '前へ',
     'filter_active' => '有効なフィルター:',
     'filter_clear' => 'フィルターを解除',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => '並べ替えオプション',
index 3ef87f8a1bb4f8517eee0e20911600b345cfd3fb..6f7b237548bbd3ac06bc72686ff7cfa8375e97e6 100644 (file)
@@ -328,7 +328,7 @@ return [
     'comment' => 'コメント',
     'comments' => 'コメント',
     'comment_add' => 'コメント追加',
-    'comment_placeholder' => 'コメントを記入してくさい',
+    'comment_placeholder' => 'コメントを記入してくさい',
     'comment_count' => '{0} コメントはありません|[1,*] コメント:count件',
     'comment_save' => 'コメントを保存',
     'comment_saving' => 'コメントを保存中...',
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'ページの画像ファイルは複製されず、元の画像は最初にアップロードされたページとの関係を保持します。',
     'copy_consider_attachments' => 'ページの添付ファイルはコピーされません。',
     'copy_consider_access' => '場所、所有者または権限を変更すると、以前アクセスできなかったユーザーがこのコンテンツにアクセスできるようになる可能性があります。',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 1ea53b80ae5ed31448a2627a420b723ab95a30f3..a4e39a8381ed930ba206cd89147cf99826d6fd7c 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => '책자 만들기',
     'book_create_notification'    => '책 생성함',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => '책 수정',
     'book_update_notification'    => '책 수정함',
     'book_delete'                 => '책 지우기',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => '책꽂이 만들기',
     'bookshelf_create_notification'    => '책꽂이 생성함',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => '책꽂이 수정',
     'bookshelf_update_notification'    => '책꽂이 수정함',
     'bookshelf_delete'                 => '책꽂이 지우기',
index 284ab3352a687525409acbcb7a770657cd1158b9..0cd6f873e202956c11e94624ee58b77a791edf7b 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => '이 메일 주소로는 이 사이트에 접근할 수 없습니다.',
     'register_success' => '가입했습니다! 이제 로그인할 수 있습니다.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => '패스워드 바꾸기',
     'reset_password_send_instructions' => '메일 주소를 입력하세요. 이 주소로 해당 과정을 위한 링크를 보낼 것입니다.',
index 81dc71eaa7518c933d5d236b842536300bc556f8..685a8616dffccbb064165cfb87f5b32e552dbdc9 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => '이전',
     'filter_active' => '적용 중:',
     'filter_clear' => '모든 필터 해제',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => '정렬 기준',
index 7c80d20cac7ad52af04022ba3127aecc406bd7c4..68392b0a2dd54c1a59b55535b02b69d37ab2b3d1 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => '이미지 파일은 복사되지 않습니다. 올라가 있던 이미지가 사라지지 않습니다.',
     'copy_consider_attachments' => '첨부 파일은 복사되지 않습니다.',
     'copy_consider_access' => '경로, 소유자, 권한이 바뀌면 이 문서를 본 적 없는 사용자가 볼 수도 있습니다.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index b8ac7049fb123e5fa1b629661e07c8025d2ce278..7728f48351736c0b46892a7cf70b9772365b7402 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'sukurta knyga',
     'book_create_notification'    => 'Book successfully created',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'atnaujinta knyga',
     'book_update_notification'    => 'Book successfully updated',
     'book_delete'                 => 'ištrinta knyga',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'atnaujinta knygų lentyna',
     'bookshelf_update_notification'    => 'Bookshelf successfully updated',
     'bookshelf_delete'                 => 'ištrinta knygų lentyna',
index e6b2233c1b8ce91d51a28a48ec22c144e08807ad..fb30e57ed7a8d99e1c62343dd8a376610737b09f 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Elektroninio pašto domenas neturi prieigos prie šios programos',
     'register_success' => 'Ačiū už prisijungimą! Dabar jūs užsiregistravote ir prisijungėte.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Pakeisti slaptažodį',
     'reset_password_send_instructions' => 'Įveskite savo elektroninį paštą žemiau ir jums bus išsiųstas elektroninis laiškas su slaptažodžio nustatymo nuoroda.',
index 090b86a85cdde3763fadc7779980f49f4c8231d6..962d2d9d6c80f3481d34b5537e90c7ef03aee828 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Previous',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Rūšiuoti pasirinkimus',
index c91b118305a881aa991c4a787f4d685a6c8694ce..7b2a3deee093cf219ea1a8d052ed7ffaedf12ad3 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 084f731524f443960ea7e11dfa5c96d365006b3f..c76041a0a456e2bc7d3c0b31fe676358e1b9067e 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'izveidoja grāmatu',
     'book_create_notification'    => 'Grāmata veiksmīgi izveidota',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'atjaunoja grāmatu',
     'book_update_notification'    => 'Grāmata veiksmīgi atjaunināta',
     'book_delete'                 => 'izdzēsa grāmatu',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'izveidoja plautku',
     'bookshelf_create_notification'    => 'Plaukts veiksmīgi izveidots',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'atjaunoja plauktu',
     'bookshelf_update_notification'    => 'Plaukts veiksmīgi atjaunināts',
     'bookshelf_delete'                 => 'izdzēsa plauktu',
index fd8e2e9c681f0f12be806a80206e1da712543f7a..009da6cb7092d72f4bb7776d54cb42da92db4ab0 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'E-pasta domēnam nav piekļuves pie šīs aplikācijas',
     'register_success' => 'Paldies par reģistrēšanos! Tagad varat pieslēgties.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Atiestatīt paroli',
     'reset_password_send_instructions' => 'Ievadiet savu e-pastu zemāk un nosūtīsim e-pastu ar paroles atiestatīšanas saiti.',
index e859027bc094e6a553b71255b8cd6bcfe9a4afed..64a7421c200949fb1f4a28f66cd950ec3d6e49a5 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Iepriekšējais',
     'filter_active' => 'Aktīvais filtrs:',
     'filter_clear' => 'Notīrīt filtru',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Kārtošanas Opcijas',
index 677333c5a818f742ee726e624d28011e1377b842..120b64de6ef7883860725a7951274746302d8b6e 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Lapas attēlu faili netiks kopēti un sākotnējie attēli saglabās savu saistību ar lapu, kurai tie tika sākotnēji pievienoti.',
     'copy_consider_attachments' => 'Lapai pievienotie faili netiks nokopēti.',
     'copy_consider_access' => 'Atrašanās vietas, īpašnieka vai piekļuves tiesību izmaiņas var padarīt šo saturu pieejamu citiem, kam iepriekš nav dota piekļuve.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index cbccb356e810426ddc3d234317c6207cb1cb879e..9fc367467c5fe77e341520ade6dbcf2cf804f864 100644 (file)
@@ -29,6 +29,8 @@ return [
     // Books
     'book_create'                 => 'opprettet bok',
     'book_create_notification'    => 'Book successfully created',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'oppdaterte bok',
     'book_update_notification'    => 'Book successfully updated',
     'book_delete'                 => 'slettet bok',
@@ -39,6 +41,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'oppdaterte bokhylle',
     'bookshelf_update_notification'    => 'Bookshelf successfully updated',
     'bookshelf_delete'                 => 'slettet bokhylle',
index d80b3258a542183cbe36bca27d2134525d1c2006..afeb51e54e9b7d9e4713746e72d6f4ea5f5a6192 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Du kan ikke bruke det domenet for å registrere en konto.',
     'register_success' => 'Takk for registreringen! Du kan nå logge inn på tjenesten.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Nullstille passord',
     'reset_password_send_instructions' => 'Oppgi e-posten som er koblet til kontoen din, så sender vi en epost hvor du kan nullstille passordet.',
index cc0a3b6ff0805aef18243d1f1b2a7583f6084930..43de015ac8490cddbaeb40e70b48457eb76250e3 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Forrige',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Sorteringsalternativer',
index df833e87ad616a7a3411ac82746d7e8f08144517..11b39a79e313925ed32486bdb548aea26832edc9 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index ee97aadc684af4f104112c7c44a38c60114df5f1..ab0db63b8775e22dab316f6dc21eb122b889bdb1 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'maakte boek',
     'book_create_notification'    => 'Boek succesvol aangemaakt',
+    'book_create_from_chapter'              => 'hoofdstuk omzetten naar boek',
+    'book_create_from_chapter_notification' => 'Hoofdstuk is omgezet naar een boek',
     'book_update'                 => 'wijzigde boek',
     'book_update_notification'    => 'Boek succesvol bijgewerkt',
     'book_delete'                 => 'verwijderde boek',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'boekenplank aangemaakt',
     'bookshelf_create_notification'    => 'Boekenplank succesvol aangemaakt',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'wijzigde boekenplank',
     'bookshelf_update_notification'    => 'Boekenplank succesvol bijgewerkt',
     'bookshelf_delete'                 => 'verwijderde boekenplank',
index 53c328f8fbf7554c9b1f74126d0ee5f344aac5fd..c4adb8905bb4bb31f5d91a9419ba34d8faf733e3 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Dit e-maildomein is niet toegestaan',
     'register_success' => 'Bedankt voor het aanmelden! Je bent nu geregistreerd en aangemeld.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Wachtwoord herstellen',
     'reset_password_send_instructions' => 'Geef je e-mail en we sturen je een link om je wachtwoord te herstellen',
index bd1cca8f81f7ecd89cd2c764988d007d3b2da451..f58cf8258c78f242eb4a8a24eb0616710e4fb85f 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Vorige',
     'filter_active' => 'Actieve Filter:',
     'filter_clear' => 'Wis Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open als Tabblad',
 
     // Sort Options
     'sort_options' => 'Sorteeropties',
index 03eaf9f942b00f8aa7e263692e8266eb7aa11abf..c1b2b4cfc817cd096dcac57851449b9b2e000f95 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Afbeeldingsbestanden worden niet gedupliceerd & de originele afbeeldingen behouden hun koppeling met de pagina waarop ze oorspronkelijk werden geüpload.',
     'copy_consider_attachments' => 'Pagina bijlagen worden niet gekopieerd.',
     'copy_consider_access' => 'Een verandering van locatie, eigenaar of machtigingen kan ertoe leiden dat deze inhoud toegankelijk wordt voor personen die er voordien geen toegang tot hadden.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 54f02403989e7d738cb828ca2b0ce1673718fded..2634fe3edf7c6c0ff75a8169092828e3da80257f 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'utworzył książkę',
     'book_create_notification'    => 'Książka utworzona pomyślnie',
+    'book_create_from_chapter'              => 'skonwertował rozdział na książkę',
+    'book_create_from_chapter_notification' => 'Rozdział został pomyślnie skonwertowany do książki',
     'book_update'                 => 'zaktualizował książkę',
     'book_update_notification'    => 'Książka zaktualizowana pomyślnie',
     'book_delete'                 => 'usunął książkę',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'utworzył półkę',
     'bookshelf_create_notification'    => 'Półka utworzona pomyślnie',
+    'bookshelf_create_from_book'    => 'skonwertował książkę na półkę',
+    'bookshelf_create_from_book_notification'    => 'Książka została pomyślnie skonwertowana na półkę',
     'bookshelf_update'                 => 'zaktualizował półkę',
     'bookshelf_update_notification'    => 'Półka zaktualizowana pomyślnie',
     'bookshelf_delete'                 => 'usunął półkę',
index 6d934bbdc1e9296ce40c1df34446dc4c382dda19..e7a3260f4bc4598a2a50a56cb7918e9655d00422 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Adresy e-mail z tej domeny nie mają dostępu do tej aplikacji',
     'register_success' => 'Dziękujemy za rejestrację! Zostałeś zalogowany automatycznie.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
index 7bacb698d700730e83b80cc3b9b9cc03695a16b7..e07b1849ac413b1b80acbbe7c1c70c6164116327 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Wstecz',
     'filter_active' => 'Aktywny filtr:',
     'filter_clear' => 'Wyczyść Filtr',
+    'download' => 'Pobierz',
+    'open_in_tab' => 'Otwórz w karcie',
 
     // Sort Options
     'sort_options' => 'Opcje sortowania',
index 544f374f3fe07f2708c756cc7b3e4dc6b764c61c..34d88164f27c6779f2e3dbe87c0a80b4b6f71798 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Pliki obrazów znajdujących się na stronie nie będą zduplikowane i oryginalne obrazy zachowają swój związek ze stroną, do której zostały pierwotnie przesłane.',
     'copy_consider_attachments' => 'Załączniki strony nie zostaną skopiowane.',
     'copy_consider_access' => 'Zmiana lokalizacji, właściciela lub uprawnień może spowodować, że ta zawartość będzie dostępna dla tych, którzy wcześniej nie mieli dostępu.',
+
+    // Conversions
+    'convert_to_shelf' => 'Konwertuj na półkę',
+    'convert_to_shelf_contents_desc' => 'Możesz przekonwertować tę książkę do nowej półki z tą samą zawartością. Rozdziały zawarte w tej książce zostaną przekonwertowane na nowe książki. Jeśli ta książka zawiera jakieś strony, które nie znajdują się w rozdziale, wtedy nazwa tej książki zostanie zmieniona i będzie ona zawierać te strony, a sama książka stanie się częścią nowej półki.',
+    'convert_to_shelf_permissions_desc' => 'Wszelkie uprawnienia ustawione w tej książce zostaną skopiowane do nowej półki i do wszystkich nowych książek tej półki, które nie mają własnych uprawnień. Zauważ, że uprawnienia na półkach nie są automatycznie kaskadowane do ich zawartości, tak jak to ma miejsce w przypadku książek.',
+    'convert_book' => 'Konwertuj książkę',
+    'convert_book_confirm' => 'Czy na pewno chcesz skonwertować tę książkę?',
+    'convert_undo_warning' => 'Nie da się tego łatwo cofnąć.',
+    'convert_to_book' => 'Konwertuj na książkę',
+    'convert_to_book_desc' => 'Możesz skonwertować ten rozdział do nowej książki o tej samej treści. Wszelkie uprawnienia ustawione w tym rozdziale zostaną skopiowane do nowej książki, ale wszelkie dziedziczone uprawnienia z poprzedniej nadrzędnej książki nie będą skopiowane, co może doprowadzić do zmiany w kontroli dostępu.',
+    'convert_chapter' => 'Konwertuj rozdział',
+    'convert_chapter_confirm' => 'Czy na pewno chcesz skonwertować ten rozdział?',
 ];
index 733a3cadca8a897510492920410af8371328e595..96d729422df2273c345dd813a5396305776ad5a9 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'livro criado',
     'book_create_notification'    => 'Livro criado com sucesso',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'livro atualizado',
     'book_update_notification'    => 'Livro atualizado com sucesso',
     'book_delete'                 => 'livro eliminado',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'estante criada',
     'bookshelf_create_notification'    => 'Estante criada com sucesso',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'estante atualizada',
     'bookshelf_update_notification'    => 'Estante atualizada com sucesso',
     'bookshelf_delete'                 => 'excluiu a prateleira',
index 82fb9aa236b892059d6b8823f9af1405bccc013a..ad4f0744d281b79c003156254f8363729777ddd6 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'O domínio de e-mail usado não tem acesso permitido a esta aplicação',
     'register_success' => 'Obrigado por se registar! Você está agora registado e com a sessão iniciada.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Redefinir Senha',
     'reset_password_send_instructions' => 'Insira o seu endereço de e-mail abaixo, e uma mensagem com o link de redefinição de palavra-passe será lhe enviada.',
index 137f389b32b3bdaaffc08d2102ab7fe1772ccf3f..afb857ac2c963b58f7c94de13377d03fdd8d01df 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Anterior',
     'filter_active' => 'Filtro Ativo:',
     'filter_clear' => 'Limpar Filtro',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Opções de Ordenação',
index e9bae6b56c676e43081c26eeb1dff328f5730e9c..9ee3f575ceaef4b795380e3c9ecdde88ab865e70 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'A imagem da página não será duplicada e as imagens originais manterão sua relação com a página para a qual foram enviadas originalmente.',
     'copy_consider_attachments' => 'Anexos da página não serão copiados.',
     'copy_consider_access' => 'Uma alteração de localização, proprietário ou permissões pode resultar em que este conteúdo seja acessível para aqueles previamente sem acesso.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 8e057cb92c1183010dbd44eb7d33399c6490e3d5..4f068844e231cf29d695b1c3bfa777658ee6aa58 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'criou o livro',
     'book_create_notification'    => 'Livro criado com sucesso',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'atualizou o livro',
     'book_update_notification'    => 'Livro atualizado com sucesso',
     'book_delete'                 => 'excluiu o livro',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'prateleira criada',
     'bookshelf_create_notification'    => 'Prateleira criada com sucesso',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'atualizou a prateleira',
     'bookshelf_update_notification'    => 'Prateleira atualizada com sucesso',
     'bookshelf_delete'                 => 'excluiu a prateleira',
index d9374296dc0de6ade87ffa2270f25776553d0570..17ebcb16eae1841ae7055a10295cadb8927956d8 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'O domínio de e-mail usado não tem acesso permitido a essa aplicação',
     'register_success' => 'Obrigado por se cadastrar! Você agora encontra-se cadastrado(a) e logado(a).',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
index d9f54d8a0ae8611c2b329d31d9d3fcc6ddd69e58..99aecfd923d049914a144690f4cfd779652e2065 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Anterior',
     'filter_active' => 'Filtro Ativo:',
     'filter_clear' => 'Limpar Filtro',
+    'download' => 'Baixar',
+    'open_in_tab' => 'Abrir na aba',
 
     // Sort Options
     'sort_options' => 'Opções de Ordenação',
@@ -75,7 +77,7 @@ return [
     'status_active' => 'Ativo',
     'status_inactive' => 'Inativo',
     'never' => 'Nunca',
-    'none' => 'None',
+    'none' => 'Nenhum',
 
     // Header
     'header_menu_expand' => 'Expandir Cabeçalho do Menu',
index efd0e265590ebb2501cdfe9dbbeed635a2ea5770..4ee5ba30510aeb244e15945e82de8ddbfc81eb15 100644 (file)
@@ -24,148 +24,148 @@ return [
     'width' => 'Largura',
     'height' => 'Altura',
     'More' => 'Mais',
-    'select' => 'Select...',
+    'select' => 'Selecionar...',
 
     // Toolbar
     'formats' => 'Formatos',
     'header_large' => 'Cabeçalho Grande',
     'header_medium' => 'Cabeçalho Médio',
     'header_small' => 'Cabeçalho Pequeno',
-    'header_tiny' => 'Tiny Header',
+    'header_tiny' => 'Cabeçalho Pequeno',
     'paragraph' => 'Parágrafo',
     'blockquote' => 'Bloco de Citação',
-    'inline_code' => 'Inline code',
-    'callouts' => 'Callouts',
-    'callout_information' => 'Information',
-    'callout_success' => 'Success',
-    'callout_warning' => 'Warning',
-    'callout_danger' => 'Danger',
+    'inline_code' => 'Código embutido',
+    'callouts' => 'Frase de destaque',
+    'callout_information' => 'Informação',
+    'callout_success' => 'Sucesso',
+    'callout_warning' => 'Atenção',
+    'callout_danger' => 'Perigo',
     'bold' => 'Bold',
-    'italic' => 'Italic',
-    'underline' => 'Underline',
-    'strikethrough' => 'Strikethrough',
-    'superscript' => 'Superscript',
-    'subscript' => 'Subscript',
-    'text_color' => 'Text color',
-    'custom_color' => 'Custom color',
-    'remove_color' => 'Remove color',
-    'background_color' => 'Background color',
-    'align_left' => 'Align left',
-    'align_center' => 'Align center',
-    'align_right' => 'Align right',
-    'align_justify' => 'Justify',
-    'list_bullet' => 'Bullet list',
-    'list_numbered' => 'Numbered list',
-    'list_task' => 'Task list',
-    'indent_increase' => 'Increase indent',
-    'indent_decrease' => 'Decrease indent',
-    'table' => 'Table',
-    'insert_image' => 'Insert image',
-    'insert_image_title' => 'Insert/Edit Image',
-    'insert_link' => 'Insert/edit link',
-    'insert_link_title' => 'Insert/Edit Link',
+    'italic' => 'Itálico',
+    'underline' => 'Sublinhar',
+    'strikethrough' => 'Riscado',
+    'superscript' => 'Superinscrição',
+    'subscript' => 'Subscrição',
+    'text_color' => 'Cor do texto',
+    'custom_color' => 'Cor personalizada',
+    'remove_color' => 'Remover cor',
+    'background_color' => 'Cor de fundo',
+    'align_left' => 'Alinhar à esquerda',
+    'align_center' => 'Alinhar ao centro',
+    'align_right' => 'Alinhar à direita',
+    'align_justify' => 'Justificar',
+    'list_bullet' => 'Lista com marcadores',
+    'list_numbered' => 'Lista numerada',
+    'list_task' => 'Lista de tarefas',
+    'indent_increase' => 'Aumentar recuo',
+    'indent_decrease' => 'Diminuir recuo',
+    'table' => 'Mesa',
+    'insert_image' => 'Inserir Imagem',
+    'insert_image_title' => 'Inserir/Editar imagem',
+    'insert_link' => 'Inserir/editar link',
+    'insert_link_title' => 'Inserir/Editar link',
     'insert_horizontal_line' => 'Insert horizontal line',
-    'insert_code_block' => 'Insert code block',
-    'insert_drawing' => 'Insert/edit drawing',
-    'drawing_manager' => 'Drawing manager',
-    'insert_media' => 'Insert/edit media',
-    'insert_media_title' => 'Insert/Edit Media',
-    'clear_formatting' => 'Clear formatting',
-    'source_code' => 'Source code',
-    'source_code_title' => 'Source Code',
-    'fullscreen' => 'Fullscreen',
-    'image_options' => 'Image options',
+    'insert_code_block' => 'Inserir o bloco de endereço',
+    'insert_drawing' => 'Inserir/editar desenho',
+    'drawing_manager' => 'Gerente de desenho',
+    'insert_media' => 'Inserir/editar mídia',
+    'insert_media_title' => 'Inserir/Editar Mídia',
+    'clear_formatting' => 'Limpar formatação',
+    'source_code' => 'Código fonte',
+    'source_code_title' => 'Código fonte',
+    'fullscreen' => 'Tela cheia',
+    'image_options' => 'Opções de imagem',
 
     // Tables
-    'table_properties' => 'Table properties',
-    'table_properties_title' => 'Table Properties',
-    'delete_table' => 'Delete table',
-    'insert_row_before' => 'Insert row before',
-    'insert_row_after' => 'Insert row after',
-    'delete_row' => 'Delete row',
-    'insert_column_before' => 'Insert column before',
-    'insert_column_after' => 'Insert column after',
-    'delete_column' => 'Delete column',
-    'table_cell' => 'Cell',
-    'table_row' => 'Row',
-    'table_column' => 'Column',
-    'cell_properties' => 'Cell properties',
-    'cell_properties_title' => 'Cell Properties',
-    'cell_type' => 'Cell type',
-    'cell_type_cell' => 'Cell',
-    'cell_scope' => 'Scope',
-    'cell_type_header' => 'Header cell',
-    'merge_cells' => 'Merge cells',
-    'split_cell' => 'Split cell',
-    'table_row_group' => 'Row Group',
-    'table_column_group' => 'Column Group',
-    'horizontal_align' => 'Horizontal align',
-    'vertical_align' => 'Vertical align',
-    'border_width' => 'Border width',
-    'border_style' => 'Border style',
-    'border_color' => 'Border color',
-    'row_properties' => 'Row properties',
-    'row_properties_title' => 'Row Properties',
-    'cut_row' => 'Cut row',
-    'copy_row' => 'Copy row',
-    'paste_row_before' => 'Paste row before',
-    'paste_row_after' => 'Paste row after',
-    'row_type' => 'Row type',
-    'row_type_header' => 'Header',
-    'row_type_body' => 'Body',
-    'row_type_footer' => 'Footer',
-    'alignment' => 'Alignment',
-    'cut_column' => 'Cut column',
-    'copy_column' => 'Copy column',
-    'paste_column_before' => 'Paste column before',
-    'paste_column_after' => 'Paste column after',
-    'cell_padding' => 'Cell padding',
-    'cell_spacing' => 'Cell spacing',
-    'caption' => 'Caption',
-    'show_caption' => 'Show caption',
-    'constrain' => 'Constrain proportions',
-    'cell_border_solid' => 'Solid',
-    'cell_border_dotted' => 'Dotted',
-    'cell_border_dashed' => 'Dashed',
-    'cell_border_double' => 'Double',
-    'cell_border_groove' => 'Groove',
-    'cell_border_ridge' => 'Ridge',
-    'cell_border_inset' => 'Inset',
-    'cell_border_outset' => 'Outset',
-    'cell_border_none' => 'None',
-    'cell_border_hidden' => 'Hidden',
+    'table_properties' => 'Propriedades da tabela',
+    'table_properties_title' => 'Propriedades da Tabela',
+    'delete_table' => 'Excluir Tabela',
+    'insert_row_before' => 'Inserir linha antes',
+    'insert_row_after' => 'Inserir linha depois',
+    'delete_row' => 'Excluir linha',
+    'insert_column_before' => 'Inserir coluna antes',
+    'insert_column_after' => 'Inserir coluna depois',
+    'delete_column' => 'Excluir coluna',
+    'table_cell' => 'Celular',
+    'table_row' => 'Linha',
+    'table_column' => 'Coluna',
+    'cell_properties' => 'Propriedades da célula',
+    'cell_properties_title' => 'Propriedades da Célula',
+    'cell_type' => 'Tipo de célula',
+    'cell_type_cell' => 'Célula',
+    'cell_scope' => 'Escopo',
+    'cell_type_header' => 'Célula do cabeçalho',
+    'merge_cells' => 'Mesclar células',
+    'split_cell' => 'Dividir célula',
+    'table_row_group' => 'Grupo de linha',
+    'table_column_group' => 'Grupo de coluna',
+    'horizontal_align' => 'Alinhamento Horizontal',
+    'vertical_align' => 'Alinhamento vertical',
+    'border_width' => 'Largura da borda',
+    'border_style' => 'Estilo da Borda',
+    'border_color' => 'Cor da borda',
+    'row_properties' => 'Propriedades da linha',
+    'row_properties_title' => 'Propriedades da Linha',
+    'cut_row' => 'Cortar linha',
+    'copy_row' => 'Copiar linha',
+    'paste_row_before' => 'Colar linha antes',
+    'paste_row_after' => 'Colar linha depois',
+    'row_type' => 'Tipo de linha',
+    'row_type_header' => 'Cabeçalho',
+    'row_type_body' => 'Corpo',
+    'row_type_footer' => 'Rodapé',
+    'alignment' => 'Alinhamento',
+    'cut_column' => 'Cortar coluna',
+    'copy_column' => 'Copiar Coluna',
+    'paste_column_before' => 'Colar coluna antes',
+    'paste_column_after' => 'Colar coluna depois',
+    'cell_padding' => 'Preenchimento da celula',
+    'cell_spacing' => 'Espaçamento entre células',
+    'caption' => 'Legenda',
+    'show_caption' => 'Mostrar legenda',
+    'constrain' => 'Restringir proporções',
+    'cell_border_solid' => 'Sólida',
+    'cell_border_dotted' => 'Pontilhado',
+    'cell_border_dashed' => 'Tracejado',
+    'cell_border_double' => 'Duplo',
+    'cell_border_groove' => 'Ranhura',
+    'cell_border_ridge' => 'Ondulado',
+    'cell_border_inset' => 'Inserir',
+    'cell_border_outset' => 'Saída',
+    'cell_border_none' => 'Nenhuma',
+    'cell_border_hidden' => 'Ocultado',
 
     // Images, links, details/summary & embed
-    'source' => 'Source',
-    'alt_desc' => 'Alternative description',
-    'embed' => 'Embed',
-    'paste_embed' => 'Paste your embed code below:',
+    'source' => 'Fonte',
+    'alt_desc' => 'Descrição alternativa',
+    'embed' => 'Embutido',
+    'paste_embed' => 'Cole seu código abaixo de incorporação:',
     'url' => 'URL',
-    'text_to_display' => 'Text to display',
-    'title' => 'Title',
-    'open_link' => 'Open link in...',
-    'open_link_current' => 'Current window',
-    'open_link_new' => 'New window',
-    'insert_collapsible' => 'Insert collapsible block',
-    'collapsible_unwrap' => 'Unwrap',
-    'edit_label' => 'Edit label',
-    'toggle_open_closed' => 'Toggle open/closed',
-    'collapsible_edit' => 'Edit collapsible block',
-    'toggle_label' => 'Toggle label',
+    'text_to_display' => 'Texto de exibição',
+    'title' => 'Título',
+    'open_link' => 'Abrir link em...',
+    'open_link_current' => 'Janelas atuais',
+    'open_link_new' => 'Nova janela',
+    'insert_collapsible' => 'Inserir bloco colapsável',
+    'collapsible_unwrap' => 'Desembrulhar',
+    'edit_label' => 'Editar etiqueta',
+    'toggle_open_closed' => 'Alternar aberto/fechado',
+    'collapsible_edit' => 'Inserir bloco colapsável',
+    'toggle_label' => 'Alternar etiqueta',
 
     // About view
-    'about' => 'About the editor',
-    'about_title' => 'About the WYSIWYG Editor',
-    'editor_license' => 'Editor License & Copyright',
-    'editor_tiny_license' => 'This editor is built using :tinyLink which is provided under an LGPL v2.1 license.',
-    'editor_tiny_license_link' => 'The copyright and license details of TinyMCE can be found here.',
-    'save_continue' => 'Save Page & Continue',
-    'callouts_cycle' => '(Keep pressing to toggle through types)',
-    'link_selector' => 'Link to content',
-    'shortcuts' => 'Shortcuts',
-    'shortcut' => 'Shortcut',
-    'shortcuts_intro' => 'The following shortcuts are available in the editor:',
-    'windows_linux' => '(Windows/Linux)',
-    'mac' => '(Mac)',
-    'description' => 'Description',
+    'about' => 'Sobre o editor',
+    'about_title' => 'Sobre o Editor WYSIWYG',
+    'editor_license' => 'Licença do Editor e Direitos Autorais',
+    'editor_tiny_license' => 'Este editor é criado utilizando :tinyLink que é fornecido sob uma licença LGPL v2.1.',
+    'editor_tiny_license_link' => 'Os dados relativos aos direitos de autor e à licença do TinyMCE podem ser encontrados aqui.',
+    'save_continue' => 'Salvar e continuar',
+    'callouts_cycle' => '(Continue pressionando para alternar através de tipos)',
+    'link_selector' => 'Link para conteúdo',
+    'shortcuts' => 'Atalhos',
+    'shortcut' => 'Atalho',
+    'shortcuts_intro' => 'Os seguintes atalhos estão disponíveis no editor:',
+    'windows_linux' => 'Windows, Linux',
+    'mac' => '(Mac))',
+    'description' => 'Descrição',
 ];
index 18edf07824c4d5c393c95656f0f6da489aa17490..e4dd60e7e47dfbb8f77db1e260f1546794cbe001 100644 (file)
@@ -27,8 +27,8 @@ return [
     'images' => 'Imagens',
     'my_recent_drafts' => 'Meus Rascunhos Recentes',
     'my_recently_viewed' => 'Visualizados por mim Recentemente',
-    'my_most_viewed_favourites' => 'My Most Viewed Favourites',
-    'my_favourites' => 'My Favourites',
+    'my_most_viewed_favourites' => 'Meus Favoritos Mais Visualizados',
+    'my_favourites' => 'Meus Favoritos',
     'no_pages_viewed' => 'Você não visualizou nenhuma página',
     'no_pages_recently_created' => 'Nenhuma página criada recentemente',
     'no_pages_recently_updated' => 'Nenhuma página atualizada recentemente',
@@ -36,7 +36,7 @@ return [
     'export_html' => 'Arquivo Web Contained',
     'export_pdf' => 'Arquivo PDF',
     'export_text' => 'Arquivo Texto',
-    'export_md' => 'Markdown File',
+    'export_md' => 'Arquivos para remarcar',
 
     // Permissions and restrictions
     'permissions' => 'Permissões',
@@ -63,7 +63,7 @@ return [
     'search_permissions_set' => 'Permissão definida',
     'search_created_by_me' => 'Criado por mim',
     'search_updated_by_me' => 'Atualizado por mim',
-    'search_owned_by_me' => 'Owned by me',
+    'search_owned_by_me' => 'Possuído por mim',
     'search_date_options' => 'Opções de Data',
     'search_updated_before' => 'Atualizado antes de',
     'search_updated_after' => 'Atualizado depois de',
@@ -99,7 +99,7 @@ return [
     'shelves_permissions' => 'Permissões da Prateleira',
     'shelves_permissions_updated' => 'Permissões da Prateleira Atualizadas',
     'shelves_permissions_active' => 'Permissões da Prateleira Ativas',
-    'shelves_permissions_cascade_warning' => 'Permissions on bookshelves do not automatically cascade to contained books. This is because a book can exist on multiple shelves. Permissions can however be copied down to child books using the option found below.',
+    'shelves_permissions_cascade_warning' => 'As permissões nas estantes não são automaticamente cascatas para conter livros. Isto ocorre porque um livro existe em várias prateleiras. As permissões podem, no entanto, ser copiadas para livros filhos usando a opção encontrada abaixo.',
     'shelves_copy_permissions_to_books' => 'Copiar Permissões para Livros',
     'shelves_copy_permissions' => 'Copiar Permissões',
     'shelves_copy_permissions_explain' => 'Isto aplicará as configurações de permissões atuais desta prateleira a todos os livros contidos nela. Antes de ativar, assegure-se de que quaisquer alterações nas permissões desta prateleira tenham sido salvas.',
@@ -143,8 +143,8 @@ return [
     'books_sort_chapters_last' => 'Capítulos por Último',
     'books_sort_show_other' => 'Mostrar Outros Livros',
     'books_sort_save' => 'Salvar Nova Ordenação',
-    'books_copy' => 'Copy Book',
-    'books_copy_success' => 'Book successfully copied',
+    'books_copy' => 'Copiar Livro',
+    'books_copy_success' => 'Livro criado com sucesso',
 
     // Chapters
     'chapter' => 'Capítulo',
@@ -163,8 +163,8 @@ return [
     'chapters_move' => 'Mover Capítulo',
     'chapters_move_named' => 'Mover Capítulo :chapterName',
     'chapter_move_success' => 'Capítulo movido para :bookName',
-    'chapters_copy' => 'Copy Chapter',
-    'chapters_copy_success' => 'Chapter successfully copied',
+    'chapters_copy' => 'Copiar Capítulo',
+    'chapters_copy_success' => 'Página copiada com sucesso',
     'chapters_permissions' => 'Permissões do Capítulo',
     'chapters_empty' => 'Nenhuma página existente nesse capítulo.',
     'chapters_permissions_active' => 'Permissões de Capítulo Ativas',
@@ -196,19 +196,19 @@ return [
     'pages_edit_draft_save_at' => 'Rascunho salvo em ',
     'pages_edit_delete_draft' => 'Excluir Rascunho',
     'pages_edit_discard_draft' => 'Descartar Rascunho',
-    'pages_edit_switch_to_markdown' => 'Switch to Markdown Editor',
-    'pages_edit_switch_to_markdown_clean' => '(Clean Content)',
-    'pages_edit_switch_to_markdown_stable' => '(Stable Content)',
-    'pages_edit_switch_to_wysiwyg' => 'Switch to WYSIWYG Editor',
+    'pages_edit_switch_to_markdown' => 'Alternar para o Editor de Markdown',
+    'pages_edit_switch_to_markdown_clean' => '(Conteúdo Limpo)',
+    'pages_edit_switch_to_markdown_stable' => '(Conteúdo Estável)',
+    'pages_edit_switch_to_wysiwyg' => 'Alternar para o Editor WYSIWYG',
     'pages_edit_set_changelog' => 'Relatar Alterações',
     'pages_edit_enter_changelog_desc' => 'Digite uma breve descrição das alterações efetuadas por você',
     'pages_edit_enter_changelog' => 'Insira Alterações',
-    'pages_editor_switch_title' => 'Switch Editor',
-    'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?',
-    'pages_editor_switch_consider_following' => 'Consider the following when changing editors:',
-    'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.',
-    'pages_editor_switch_consideration_b' => 'This can potentially lead to a loss of detail and syntax in certain circumstances.',
-    'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.',
+    'pages_editor_switch_title' => 'Trocar editor',
+    'pages_editor_switch_are_you_sure' => 'Você tem certeza que deseja alterar o editor para esta página?',
+    'pages_editor_switch_consider_following' => 'Considere o seguinte ao alterar editores:',
+    'pages_editor_switch_consideration_a' => 'Uma vez salva, a nova opção do editor será usada por quaisquer editores futuros, incluindo aqueles que podem não ser capazes de mudar o tipo do editor.',
+    'pages_editor_switch_consideration_b' => 'Isso pode levar a uma perda de detalhes e sintaxe em certas circunstâncias.',
+    'pages_editor_switch_consideration_c' => 'Etiqueta ou alterações no log de mudanças, feitas desde o último salvamento, não persistem nesta alteração.',
     'pages_save' => 'Salvar Página',
     'pages_title' => 'Título da Página',
     'pages_name' => 'Nome da Página',
@@ -235,7 +235,7 @@ return [
     'pages_revisions_number' => '#',
     'pages_revisions_numbered' => 'Revisão #:id',
     'pages_revisions_numbered_changes' => 'Alterações da Revisão #:id',
-    'pages_revisions_editor' => 'Editor Type',
+    'pages_revisions_editor' => 'Tipo de editor',
     'pages_revisions_changelog' => 'Relatório de Alterações',
     'pages_revisions_changes' => 'Alterações',
     'pages_revisions_current' => 'Versão Atual',
@@ -249,7 +249,7 @@ return [
     'pages_initial_name' => 'Nova Página',
     'pages_editing_draft_notification' => 'Você está atualmente editando um rascunho que foi salvo da última vez em :timeDiff.',
     'pages_draft_edited_notification' => 'Essa página foi atualizada desde então. É recomendado que você descarte esse rascunho.',
-    'pages_draft_page_changed_since_creation' => 'This page has been updated since this draft was created. It is recommended that you discard this draft or take care not to overwrite any page changes.',
+    'pages_draft_page_changed_since_creation' => 'Esta página foi atualizada desde que este rascunho foi criado. É recomendável que você descarte este rascunho ou tenha cuidado para não sobrescrever nenhuma alteração de página.',
     'pages_draft_edit_active' => [
         'start_a' => ':count usuários iniciaram a edição dessa página',
         'start_b' => ':userName iniciou a edição dessa página',
@@ -273,16 +273,16 @@ return [
     'tags_explain' => "Adicione algumas tags para melhor categorizar seu conteúdo. \n Você pode atribuir valores às tags para uma organização mais complexa.",
     'tags_add' => 'Adicionar outra tag',
     'tags_remove' => 'Remover essa tag',
-    'tags_usages' => 'Total tag usages',
-    'tags_assigned_pages' => 'Assigned to Pages',
-    'tags_assigned_chapters' => 'Assigned to Chapters',
-    'tags_assigned_books' => 'Assigned to Books',
-    'tags_assigned_shelves' => 'Assigned to Shelves',
-    'tags_x_unique_values' => ':count unique values',
-    'tags_all_values' => 'All values',
-    'tags_view_tags' => 'View Tags',
-    'tags_view_existing_tags' => 'View existing tags',
-    'tags_list_empty_hint' => 'Tags can be assigned via the page editor sidebar or while editing the details of a book, chapter or shelf.',
+    'tags_usages' => 'Total de marcadores usados',
+    'tags_assigned_pages' => 'Atribuído às páginas',
+    'tags_assigned_chapters' => 'Atribuído aos Capítulos',
+    'tags_assigned_books' => 'Atribuído a Livros',
+    'tags_assigned_shelves' => 'Atribuído a Prateleiras',
+    'tags_x_unique_values' => ':count valores únicos',
+    'tags_all_values' => 'Todos os valores',
+    'tags_view_tags' => 'Ver Marcadores',
+    'tags_view_existing_tags' => 'Ver tags existentes',
+    'tags_list_empty_hint' => 'As tags podem ser atribuídas através da barra lateral do editor de página ou ao editar os detalhes de um livro, capítulo ou prateleira.',
     'attachments' => 'Anexos',
     'attachments_explain' => 'Faça o upload de alguns arquivos ou anexe links para serem exibidos na sua página. Eles estarão visíveis na barra lateral à direita.',
     'attachments_explain_instant_save' => 'Mudanças são salvas instantaneamente.',
@@ -349,10 +349,22 @@ return [
     'revision_cannot_delete_latest' => 'Não é possível excluir a revisão mais recente.',
 
     // Copy view
-    'copy_consider' => 'Please consider the below when copying content.',
-    'copy_consider_permissions' => 'Custom permission settings will not be copied.',
-    'copy_consider_owner' => 'You will become the owner of all copied content.',
-    'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
-    'copy_consider_attachments' => 'Page attachments will not be copied.',
-    'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+    'copy_consider' => 'Por favor, considere o abaixo ao copiar conteúdo.',
+    'copy_consider_permissions' => 'Configurações de permissão personalizada não serão copiadas.',
+    'copy_consider_owner' => 'Você se tornará o proprietário de todos os conteúdos copiados.',
+    'copy_consider_images' => 'A imagem da página não será duplicada e as imagens originais manterão sua relação com a página para a qual foram enviadas originalmente.',
+    'copy_consider_attachments' => 'Anexos de página não serão copiados.',
+    'copy_consider_access' => 'Uma alteração de localização, proprietário ou permissões pode resultar em que este conteúdo seja acessível para aqueles previamente sem acesso.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 63928f594dc695ef6ffbf5f2323b0df8bb286ad1..1ebc28f8cc8fa734bd90a47a02628f5a65e6c166 100644 (file)
@@ -23,10 +23,10 @@ return [
     'saml_no_email_address' => 'Não foi possível encontrar um endereço de e-mail para este usuário nos dados providos pelo sistema de autenticação externa',
     'saml_invalid_response_id' => 'A requisição do sistema de autenticação externa não foi reconhecia por um processo iniciado por esta aplicação. Após o login, navegar para o caminho anterior pode causar um problema.',
     'saml_fail_authed' => 'Login utilizando :system falhou. Sistema não forneceu autorização bem sucedida',
-    'oidc_already_logged_in' => 'Already logged in',
-    'oidc_user_not_registered' => 'The user :name is not registered and automatic registration is disabled',
-    'oidc_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system',
-    'oidc_fail_authed' => 'Login using :system failed, system did not provide successful authorization',
+    'oidc_already_logged_in' => 'Já está logado',
+    'oidc_user_not_registered' => 'O usuário :name não está registrado e o registro automático está desativado',
+    'oidc_no_email_address' => 'Não foi possível encontrar um endereço de e-mail para este usuário, nos dados fornecidos pelo sistema de autenticação externa',
+    'oidc_fail_authed' => 'Login usando :system falhou, o sistema não forneceu autorização com sucesso',
     'social_no_action_defined' => 'Nenhuma ação definida',
     'social_login_bad_response' => "Erro recebido durante o login :socialAccount: \n:error",
     'social_account_in_use' => 'Essa conta :socialAccount já está em uso. Por favor, tente entrar utilizando a opção :socialAccount.',
@@ -87,9 +87,9 @@ return [
     '404_page_not_found' => 'Página Não Encontrada',
     'sorry_page_not_found' => 'Desculpe, a página que você está procurando não pôde ser encontrada.',
     'sorry_page_not_found_permission_warning' => 'Se você esperava que esta página existisse, talvez você não tenha permissão para visualizá-la.',
-    'image_not_found' => 'Image Not Found',
-    'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
-    'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
+    'image_not_found' => 'Imagem não encontrada',
+    'image_not_found_subtitle' => 'Desculpe, o arquivo de imagem que você estava procurando não pôde ser encontrado.',
+    'image_not_found_details' => 'Se você esperava que esta imagem existisse, ela pode ter sido excluída.',
     'return_home' => 'Retornar à página inicial',
     'error_occurred' => 'Ocorreu um Erro',
     'app_down' => ':appName está fora do ar no momento',
index a9b53277f32bf49512f1f1fd93c4c69a5ab07485..8773ce8653781e265bab0c1d70579fd3733aeda6 100644 (file)
@@ -10,8 +10,8 @@ return [
     'settings' => 'Configurações',
     'settings_save' => 'Salvar Configurações',
     'settings_save_success' => 'Configurações salvas',
-    'system_version' => 'System Version',
-    'categories' => 'Categories',
+    'system_version' => 'Versão do Sistema',
+    'categories' => 'Categorias',
 
     // App Settings
     'app_customization' => 'Customização',
@@ -27,8 +27,8 @@ return [
     'app_secure_images' => 'Upload de Imagens mais Seguro',
     'app_secure_images_toggle' => 'Habilitar uploads de imagem mais seguro',
     'app_secure_images_desc' => 'Por razões de performance, todas as imagens são públicas. Esta opção adiciona uma string randômica na frente das URLs de imagens. Certifique-se de que os diretórios não possam ser indexados para prevenir acesso indesejado.',
-    'app_default_editor' => 'Default Page Editor',
-    'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.',
+    'app_default_editor' => 'Editor de Página Padrão',
+    'app_default_editor_desc' => 'Selecione qual editor será usado por padrão ao editar novas páginas. Isso pode ser substituído em um nível de página onde é permitido.',
     'app_custom_html' => 'Conteúdo customizado para <head> HTML',
     'app_custom_html_desc' => 'Quaisquer conteúdos aqui adicionados serão inseridos no final da seção <head> de cada página. Essa é uma maneira útil de sobrescrever estilos e adicionar códigos de análise de site.',
     'app_custom_html_disabled_notice' => 'O conteúdo customizado do <head> HTML está desabilitado nesta página de configurações, para garantir que quaisquer alterações danosas possam ser revertidas.',
@@ -94,7 +94,7 @@ return [
     'recycle_bin' => 'Lixeira',
     'recycle_bin_desc' => 'Aqui você pode restaurar itens que foram excluídos ou escolher removê-los permanentemente do sistema. Esta lista não é filtrada diferentemente de listas de atividades similares no sistema onde filtros de permissão são aplicados.',
     'recycle_bin_deleted_item' => 'Item excluído',
-    'recycle_bin_deleted_parent' => 'Parent',
+    'recycle_bin_deleted_parent' => 'Parente',
     'recycle_bin_deleted_by' => 'Excluído por',
     'recycle_bin_deleted_at' => 'Momento de Exclusão',
     'recycle_bin_permanently_delete' => 'Excluir permanentemente',
@@ -106,25 +106,25 @@ return [
     'recycle_bin_destroy_list' => 'Itens a serem Destruídos',
     'recycle_bin_restore_list' => 'Itens a serem restaurados',
     'recycle_bin_restore_confirm' => 'Esta ação irá restaurar o item excluído, inclusive quaisquer elementos filhos, para seu local original. Se a localização original tiver, entretanto, sido eliminada e estiver agora na lixeira, o item pai também precisará ser restaurado.',
-    'recycle_bin_restore_deleted_parent' => 'The parent of this item has also been deleted. These will remain deleted until that parent is also restored.',
-    'recycle_bin_restore_parent' => 'Restore Parent',
-    'recycle_bin_destroy_notification' => 'Deleted :count total items from the recycle bin.',
-    'recycle_bin_restore_notification' => 'Restored :count total items from the recycle bin.',
+    'recycle_bin_restore_deleted_parent' => 'O pai deste \'item\' também foi excluído. Eles permanecerão excluídos até que o pai também seja restaurado.',
+    'recycle_bin_restore_parent' => 'Restaurar Parente',
+    'recycle_bin_destroy_notification' => 'Excluído: conta o total de itens da lixeira.',
+    'recycle_bin_restore_notification' => 'Excluído: conta o total de itens da lixeira.',
 
     // Audit Log
     'audit' => 'Registro de auditoria',
-    'audit_desc' => 'This audit log displays a list of activities tracked in the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
+    'audit_desc' => 'Este log de auditoria exibe uma lista de atividades rastreadas no sistema. Essa lista não é filtrada, ao contrário de listas de atividades semelhantes no sistema em que os filtros de permissão são aplicados.',
     'audit_event_filter' => 'Filtro de Eventos',
     'audit_event_filter_no_filter' => 'Sem filtro',
     'audit_deleted_item' => 'Item excluído',
     'audit_deleted_item_name' => 'Nome: :name',
     'audit_table_user' => 'Usuário',
     'audit_table_event' => 'Evento',
-    'audit_table_related' => 'Related Item or Detail',
-    'audit_table_ip' => 'IP Address',
+    'audit_table_related' => '\'Item\' ou Detalhe Relacionado',
+    'audit_table_ip' => 'Endereço IP',
     'audit_table_date' => 'Data da Atividade',
-    'audit_date_from' => 'Date Range From',
-    'audit_date_to' => 'Date Range To',
+    'audit_date_from' => 'Período de',
+    'audit_date_to' => 'Para',
 
     // Role Settings
     'roles' => 'Cargos',
@@ -141,7 +141,7 @@ return [
     'role_details' => 'Detalhes do Cargo',
     'role_name' => 'Nome do Cargo',
     'role_desc' => 'Breve Descrição do Cargo',
-    'role_mfa_enforced' => 'Requires Multi-Factor Authentication',
+    'role_mfa_enforced' => 'Requer Autenticação Multi-fator',
     'role_external_auth_id' => 'IDs de Autenticação Externa',
     'role_system' => 'Permissões do Sistema',
     'role_manage_users' => 'Gerenciar usuários',
@@ -151,8 +151,8 @@ return [
     'role_manage_page_templates' => 'Gerenciar modelos de página',
     'role_access_api' => 'Acessar API do sistema',
     'role_manage_settings' => 'Gerenciar configurações da aplicação',
-    'role_export_content' => 'Export content',
-    'role_editor_change' => 'Change page editor',
+    'role_export_content' => 'Exportar conteúdo',
+    'role_editor_change' => 'Alterar página de edição',
     'role_asset' => 'Permissões de Ativos',
     'roles_system_warning' => 'Esteja ciente de que o acesso a qualquer uma das três permissões acima pode permitir que um usuário altere seus próprios privilégios ou privilégios de outros usuários no sistema. Apenas atribua cargos com essas permissões para usuários confiáveis.',
     'role_asset_desc' => 'Essas permissões controlam o acesso padrão para os ativos dentro do sistema. Permissões em Livros, Capítulos e Páginas serão sobrescritas por essas permissões.',
@@ -177,7 +177,7 @@ return [
     'users_role' => 'Cargos do Usuário',
     'users_role_desc' => 'Selecione os cargos aos quais este usuário será vinculado. Se um usuário for vinculado a múltiplos cargos, suas permissões serão empilhadas e ele receberá todas as habilidades dos cargos atribuídos.',
     'users_password' => 'Senha do Usuário',
-    'users_password_desc' => 'Set a password used to log-in to the application. This must be at least 8 characters long.',
+    'users_password_desc' => 'Defina uma senha usada para fazer \'login\' no aplicativo. Deve ter pelo menos 8 caracteres.',
     'users_send_invite_text' => 'Você pode escolher enviar a este usuário um convite por e-mail que o possibilitará definir sua própria senha, ou defina você uma senha.',
     'users_send_invite_option' => 'Enviar convite por e-mail',
     'users_external_auth_id' => 'ID de Autenticação Externa',
@@ -188,8 +188,8 @@ return [
     'users_delete_named' => 'Excluir :userName',
     'users_delete_warning' => 'A ação vai excluir completamente o usuário de nome \':userName\' do sistema.',
     'users_delete_confirm' => 'Tem certeza que deseja excluir esse usuário?',
-    'users_migrate_ownership' => 'Migrate Ownership',
-    'users_migrate_ownership_desc' => 'Select a user here if you want another user to become the owner of all items currently owned by this user.',
+    'users_migrate_ownership' => 'Migrar propriedade',
+    'users_migrate_ownership_desc' => 'Selecione um usuário aqui, se você deseja que outro se torne o proprietário de todos os itens atualmente pertencentes a este usuário.',
     'users_none_selected' => 'Nenhum usuário selecionado',
     'users_edit' => 'Editar Usuário',
     'users_edit_profile' => 'Editar Perfil',
@@ -208,10 +208,10 @@ return [
     'users_api_tokens_create' => 'Criar Token',
     'users_api_tokens_expires' => 'Expira',
     'users_api_tokens_docs' => 'Documentação da API',
-    'users_mfa' => 'Multi-Factor Authentication',
-    'users_mfa_desc' => 'Setup multi-factor authentication as an extra layer of security for your user account.',
-    'users_mfa_x_methods' => ':count method configured|:count methods configured',
-    'users_mfa_configure' => 'Configure Methods',
+    'users_mfa' => 'Autenticação de Múltiplos Fatores',
+    'users_mfa_desc' => 'A autenticação multi-fator adiciona outra camada de segurança à sua conta.',
+    'users_mfa_x_methods' => ':count método configurado):count métodos configurados',
+    'users_mfa_configure' => 'Configurar Métodos',
 
     // API Tokens
     'user_api_token_create' => 'Criar Token de API',
@@ -236,30 +236,30 @@ return [
 
     // Webhooks
     'webhooks' => 'Webhooks',
-    'webhooks_create' => 'Create New Webhook',
-    'webhooks_none_created' => 'No webhooks have yet been created.',
-    'webhooks_edit' => 'Edit Webhook',
-    'webhooks_save' => 'Save Webhook',
-    'webhooks_details' => 'Webhook Details',
-    'webhooks_details_desc' => 'Provide a user friendly name and a POST endpoint as a location for the webhook data to be sent to.',
-    'webhooks_events' => 'Webhook Events',
-    'webhooks_events_desc' => 'Select all the events that should trigger this webhook to be called.',
-    'webhooks_events_warning' => 'Keep in mind that these events will be triggered for all selected events, even if custom permissions are applied. Ensure that use of this webhook won\'t expose confidential content.',
-    'webhooks_events_all' => 'All system events',
-    'webhooks_name' => 'Webhook Name',
-    'webhooks_timeout' => 'Webhook Request Timeout (Seconds)',
-    'webhooks_endpoint' => 'Webhook Endpoint',
-    'webhooks_active' => 'Webhook Active',
-    'webhook_events_table_header' => 'Events',
-    'webhooks_delete' => 'Delete Webhook',
-    'webhooks_delete_warning' => 'This will fully delete this webhook, with the name \':webhookName\', from the system.',
-    'webhooks_delete_confirm' => 'Are you sure you want to delete this webhook?',
-    'webhooks_format_example' => 'Webhook Format Example',
-    'webhooks_format_example_desc' => 'Webhook data is sent as a POST request to the configured endpoint as JSON following the format below. The "related_item" and "url" properties are optional and will depend on the type of event triggered.',
-    'webhooks_status' => 'Webhook Status',
-    'webhooks_last_called' => 'Last Called:',
-    'webhooks_last_errored' => 'Last Errored:',
-    'webhooks_last_error_message' => 'Last Error Message:',
+    'webhooks_create' => 'Criar novo webhook',
+    'webhooks_none_created' => 'Nenhum webhooks foi criado ainda.',
+    'webhooks_edit' => 'Editar webhook',
+    'webhooks_save' => 'Salvar webhook',
+    'webhooks_details' => 'Detalhes do Webhook',
+    'webhooks_details_desc' => 'Forneça um nome amigável e um endpoint POST como um local para que os dados de webhook sejam enviados.',
+    'webhooks_events' => 'Eventos de webhook',
+    'webhooks_events_desc' => 'Selecionar todos os eventos que devem acionar este webhook para serem chamados.',
+    'webhooks_events_warning' => 'Tenha em mente que esses eventos serão acionados para todos os eventos selecionados, mesmo se as permissões personalizadas forem aplicadas. Certifique-se de que o uso deste webhook não exponha conteúdo confidencial.',
+    'webhooks_events_all' => 'Todos eventos do sistema',
+    'webhooks_name' => 'Nome Webhook',
+    'webhooks_timeout' => 'Solicitação de Webhook Timeout (Segundos)',
+    'webhooks_endpoint' => 'Endpoint Webhook',
+    'webhooks_active' => 'Webhook ativo',
+    'webhook_events_table_header' => 'Eventos',
+    'webhooks_delete' => 'Excluir webhook',
+    'webhooks_delete_warning' => 'Isto irá excluir completamente este webhook, com o nome ":webhookName" do sistema.',
+    'webhooks_delete_confirm' => 'Tem certeza que deseja excluir este webhook?',
+    'webhooks_format_example' => 'Exemplo de formato Webhook',
+    'webhooks_format_example_desc' => 'Os dados do Webhook são enviados como uma solicitação POST para o ponto de extremidade configurado como JSON seguindo o formato abaixo. As propriedades "related_item" e "url" são opcionais e dependerão do tipo de evento acionado.',
+    'webhooks_status' => 'Estado do "Webhook"',
+    'webhooks_last_called' => 'Última chamada:',
+    'webhooks_last_errored' => 'Último Erro:',
+    'webhooks_last_error_message' => 'Última mensagem de erro:',
 
 
     //! If editing translations files directly please ignore this in all
index 9c778f6b983395c179dbf21e4276bf75d0d12f05..68b85029843614f82b519e0870c49a68bb51f58f 100644 (file)
@@ -32,7 +32,7 @@ return [
     'digits_between'       => 'O campo :attribute deve ter entre :min e :max dígitos.',
     'email'                => 'O campo :attribute deve ser um e-mail válido.',
     'ends_with' => 'O campo :attribute deve terminar com um dos seguintes: :values',
-    'file'                 => 'The :attribute must be provided as a valid file.',
+    'file'                 => 'O :attribute deve ser um arquivo válido.',
     'filled'               => 'O campo :attribute é requerido.',
     'gt'                   => [
         'numeric' => 'O campo :attribute deve ser maior que :value.',
index a015e183d9c41804a9347023353a0f078a962f54..d0c7adea9769b0086706346b858782eb65b75978 100644 (file)
@@ -6,7 +6,7 @@
 return [
 
     // Pages
-    'page_create'                 => 'создал страницу',
+    'page_create'                 => 'Создать страницу',
     'page_create_notification'    => 'Страница успешно создана',
     'page_update'                 => 'обновил страницу',
     'page_update_notification'    => 'Страница успешно обновлена',
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'создал книгу',
     'book_create_notification'    => 'Книга успешно создана',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'обновил книгу',
     'book_update_notification'    => 'Книга успешно обновлена',
     'book_delete'                 => 'удалил книгу',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'создал полку',
     'bookshelf_create_notification'    => 'Полка успешно создана',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'обновил полку',
     'bookshelf_update_notification'    => 'Полка успешно обновлена',
     'bookshelf_delete'                 => 'удалил полку',
index 653b5ac81a4d54c61930f4336fc07059acad0c35..e0b5e21edd1981c6124b81299bc24b46df717897 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Данный домен электронной почты недоступен для регистрации',
     'register_success' => 'Спасибо за регистрацию! Регистрация и вход в систему выполнены.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Сброс пароля',
     'reset_password_send_instructions' => 'Введите свой адрес электронной почты ниже, и вам будет отправлено письмо со ссылкой для сброса пароля.',
index 07fd17ad0685422d9019ea168232eb6576a8b8d2..8a684bc4fdb17ed90678104c568d064d87666dff 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Предыдущая',
     'filter_active' => 'Активный фильтр:',
     'filter_clear' => 'Сбросить фильтр',
+    'download' => 'Загрузить',
+    'open_in_tab' => 'Открыть во вкладке',
 
     // Sort Options
     'sort_options' => 'Параметры сортировки',
index 80a5e6b6169be02afdec87926a70a2c30d5a9884..8bf57b2eee4c56d93fda45e439eb4220623ff588 100644 (file)
@@ -196,19 +196,19 @@ return [
     'pages_edit_draft_save_at' => 'Черновик сохранён в ',
     'pages_edit_delete_draft' => 'Удалить черновик',
     'pages_edit_discard_draft' => 'Отменить черновик',
-    'pages_edit_switch_to_markdown' => 'Switch to Markdown Editor',
-    'pages_edit_switch_to_markdown_clean' => '(Clean Content)',
-    'pages_edit_switch_to_markdown_stable' => '(Stable Content)',
-    'pages_edit_switch_to_wysiwyg' => 'Switch to WYSIWYG Editor',
+    'pages_edit_switch_to_markdown' => 'Переключиться на Markdown',
+    'pages_edit_switch_to_markdown_clean' => 'Только Markdown (с возможными потерями форматирования)',
+    'pages_edit_switch_to_markdown_stable' => 'Полное сохранение форматирования (HTML)',
+    'pages_edit_switch_to_wysiwyg' => 'Переключиться в WYSIWYG',
     'pages_edit_set_changelog' => 'Задать список изменений',
     'pages_edit_enter_changelog_desc' => 'Введите краткое описание внесенных изменений',
     'pages_edit_enter_changelog' => 'Введите список изменений',
-    'pages_editor_switch_title' => 'Switch Editor',
-    'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?',
-    'pages_editor_switch_consider_following' => 'Consider the following when changing editors:',
-    'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.',
-    'pages_editor_switch_consideration_b' => 'This can potentially lead to a loss of detail and syntax in certain circumstances.',
-    'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.',
+    'pages_editor_switch_title' => 'Переключить редактор',
+    'pages_editor_switch_are_you_sure' => 'Вы уверены, что хотите изменить редактор для этой страницы?',
+    'pages_editor_switch_consider_following' => 'При изменении редактора учитывайте следующее:',
+    'pages_editor_switch_consideration_a' => 'После сохранения новая опция редактора будет использоваться любыми пользователями, которые будут редактировать данную страницу, включая тех, которые не смогут самостоятельно изменить тип редактора.',
+    'pages_editor_switch_consideration_b' => 'Это потенциально может привести к потере деталей и синтаксиса при определенных обстоятельствах.',
+    'pages_editor_switch_consideration_c' => 'Изменения в тегах или журнале, сделанные с момента последнего сохранения, не сохраняются в этом изменении.',
     'pages_save' => 'Сохранить страницу',
     'pages_title' => 'Заголовок страницы',
     'pages_name' => 'Название страницы',
@@ -235,7 +235,7 @@ return [
     'pages_revisions_number' => '#',
     'pages_revisions_numbered' => 'Версия #:id',
     'pages_revisions_numbered_changes' => 'Изменения в версии #:id',
-    'pages_revisions_editor' => 'Editor Type',
+    'pages_revisions_editor' => 'Тип редактора',
     'pages_revisions_changelog' => 'Список изменений',
     'pages_revisions_changes' => 'Изменения',
     'pages_revisions_current' => 'Текущая версия',
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Файлы изображений страницы не будут дублироваться и исходные изображения сохранят их отношение к странице, в которую они были загружены изначально.',
     'copy_consider_attachments' => 'Вложения страницы не будут скопированы.',
     'copy_consider_access' => 'Изменение положения, владельца или разрешений может привести к тому, что контент будет доступен пользователям, у которых не было доступа ранее.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 2daf99cd04efaaa274b2b0fae5345d06e192ceaf..4da8e7cfac84af719acd7e62a916536f70bb4b08 100755 (executable)
@@ -27,8 +27,8 @@ return [
     'app_secure_images' => 'Загрузка изображений с высоким уровнем безопасности',
     'app_secure_images_toggle' => 'Включить загрузку изображений с высоким уровнем безопасности',
     'app_secure_images_desc' => 'Для высокой производительности все изображения являются общедоступными. Этот параметр добавляет случайную строку перед URL изображения. Убедитесь, что индексация каталогов отключена, для предотвращения легкого доступа.',
-    'app_default_editor' => 'Default Page Editor',
-    'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.',
+    'app_default_editor' => 'Редактор страниц по умолчанию',
+    'app_default_editor_desc' => 'Выберите, какой редактор будет использоваться по умолчанию при редактировании новых страниц. Это может быть переопределено на уровне страницы, где разрешены права.',
     'app_custom_html' => 'Пользовательский контент заголовка HTML',
     'app_custom_html_desc' => 'Любой контент, добавленный здесь, будет вставлен в нижнюю часть раздела <head> каждой страницы. Это удобно для переопределения стилей или добавления кода аналитики.',
     'app_custom_html_disabled_notice' => 'Пользовательский контент заголовка HTML отключен на этой странице, чтобы гарантировать отмену любых критических изменений.',
@@ -152,7 +152,7 @@ return [
     'role_access_api' => 'Доступ к системному API',
     'role_manage_settings' => 'Управление настройками приложения',
     'role_export_content' => 'Экспорт контента',
-    'role_editor_change' => 'Change page editor',
+    'role_editor_change' => 'Изменение редактора страниц',
     'role_asset' => 'Права доступа к материалам',
     'roles_system_warning' => 'Имейте в виду, что доступ к любому из указанных выше трех разрешений может позволить пользователю изменить свои собственные привилегии или привилегии других пользователей системы. Назначать роли с этими правами можно только доверенным пользователям.',
     'role_asset_desc' => 'Эти разрешения контролируют доступ по умолчанию к параметрам внутри системы. Разрешения на книги, главы и страницы перезапишут эти разрешения.',
index 79f418456d1fcf8dd55e48417cad64cc77bcbc17..7d4a69303cb4a6e7fb4618d85b0cc8a6c8b56d01 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'vytvoril(a) knihu',
     'book_create_notification'    => 'Kniha úspešne vytvorená',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'aktualizoval(a) knihu',
     'book_update_notification'    => 'Kniha úspešne aktualizovaná',
     'book_delete'                 => 'odstránil(a) knihu',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'vytvoril(a) knižnicu',
     'bookshelf_create_notification'    => 'Knižnica úspešne vytvorená',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'aktualizoval(a) knižnicu',
     'bookshelf_update_notification'    => 'Knižnica úspešne aktualizovaná',
     'bookshelf_delete'                 => 'odstránil(a) knižnicu',
index bed111b05a2fe6283ca720018022033a72ff92df..de1484d4494e58c358fa97c80d1d4e303a48fb3c 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Táto e-mailová doména nemá prístup k tejto aplikácii',
     'register_success' => 'Ďakujeme za registráciu! Teraz ste registrovaný a prihlásený.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Resetovanie hesla',
     'reset_password_send_instructions' => 'Nižšie zadajte svoj e-mail, na ktorý Vám zašleme odkaz pre resetovanie hesla.',
index 83fb307e40389b933af69e9105623f2bf7cdaf23..85e6a7c206d1803f05d58a06936c538ac9e17a88 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Späť',
     'filter_active' => 'Aktívny filter:',
     'filter_clear' => 'Bez filtrovania',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Možnosti triedenia',
index 4cb0a0ed341b90b08637fe77bf08804ab37a669b..cfa87e0b87230d946a38e53355a696ebdbb3da48 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index a27999a787093ffb0729a97f58eacbd324367d23..96ca48464040e11d2ca7088c953f3d4faa140c01 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'knjiga ustvarjena',
     'book_create_notification'    => 'Book successfully created',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'knjiga posodobljena',
     'book_update_notification'    => 'Book successfully updated',
     'book_delete'                 => 'izbrisana knjiga',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'knjižna polica posodobljena',
     'bookshelf_update_notification'    => 'Bookshelf successfully updated',
     'bookshelf_delete'                 => 'knjižna polica izbrisana',
index bb45fa8651d9bf515580e07cca1d80a9755302f3..e667cb71ca59bc03b6217f26118f14c35a2f960c 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Ta e-poštna domena nima dostopa do te aplikacije',
     'register_success' => 'Hvala za registracijo! Sedaj ste registrirani in prijavljeni.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
index 25c4f62f7381342f7574a92d0d85f51425739d1f..4e352828ec80520685d40a9bc223a60dc906aa5a 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Previous',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Možnosti razvrščanja',
index c5fb5c35bb3517b44dcefb063e562e97748fbd76..a76bcfa267987030f25f07213ca11d4c9710b67d 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 65b20c1db19846aff508154f4428722e16875c67..fbd5115ad949709bf88e86e15831392a07a6e0fe 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'skapade boken',
     'book_create_notification'    => 'Book successfully created',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'uppdaterade boken',
     'book_update_notification'    => 'Book successfully updated',
     'book_delete'                 => 'tog bort boken',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'created bookshelf',
     'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'uppdaterade hyllan',
     'bookshelf_update_notification'    => 'Bookshelf successfully updated',
     'bookshelf_delete'                 => 'tog bort hyllan',
index 7c0907f51826819f44b869a530d9fd9e07ab674e..849918cdc1527b628ba2a05b84a5a18eb05a9e0f 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Den e-postadressen har inte tillgång till den här applikationen',
     'register_success' => 'Tack för din registrering! Du är nu registerad och inloggad.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
index 8cbaa10cca04e69b4bd007a3345840dc00140133..3f920500ddcdac3bad4e0b81dd8cd73a3c4da7f5 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Föregående',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Sorteringsalternativ',
index 943cb53615d5a69fce2a7cffc3b47e9f87da0654..c356ea5bd97894624491d2c1fd40c88eae4e7956 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index ee11a89bfbff0c369069e755aa78601ffa502074..d2b6f77b40883a57621bc409cdfc6b74ef22541b 100644 (file)
@@ -13,7 +13,7 @@ return [
     'page_delete'                 => 'sayfayı sildi',
     'page_delete_notification'    => 'Sayfa başarıyla silindi',
     'page_restore'                => 'sayfayı eski haline getirdi',
-    'page_restore_notification'   => 'Sayfa başarıyla kurtarıldı',
+    'page_restore_notification'   => 'Sayfa Başarıyla Eski Haline Getirildi',
     'page_move'                   => 'sayfayı taşıdı',
 
     // Chapters
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'kitap oluşturdu',
     'book_create_notification'    => 'Kitap başarıyla oluşturuldu',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'kitabı güncelledi',
     'book_update_notification'    => 'Kitap başarıyla güncellendi',
     'book_delete'                 => 'kitabı sildi',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'kitaplık oluşturuldu',
     'bookshelf_create_notification'    => 'Kitaplık başarıyla oluşturuldu',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'kitaplığı güncelledi',
     'bookshelf_update_notification'    => 'Kitaplık başarıyla güncellendi',
     'bookshelf_delete'                 => 'kitaplığı sildi',
index 591e7e3cff1050410c3a8241097aa43500789841..28144df2dfcb197806fc3e81755efdc3c0020579 100644 (file)
@@ -38,6 +38,11 @@ return [
     '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.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
@@ -84,15 +89,15 @@ return [
     'mfa_option_totp_title' => 'Mobil Uygulama',
     'mfa_option_totp_desc' => 'Çok aşamalı kimlik doğrulamayı kullanabilmek için Google Authenticator, Authy veya Microsoft Authenticator gibi TOTP destekleyen bir mobil uygulamaya ihtiyacınız olacaktır.',
     'mfa_option_backup_codes_title' => 'Yedekleme Kodları',
-    'mfa_option_backup_codes_desc' => 'Securely store a set of one-time-use backup codes which you can enter to verify your identity.',
+    'mfa_option_backup_codes_desc' => 'Kimliğini doğrulamak için kullanabileceğin aşağıdaki tek kullanımlık yedek kodlarını güvenli bir yerde sakla.',
     'mfa_gen_confirm_and_enable' => 'Onayla ve aktive et',
     'mfa_gen_backup_codes_title' => 'Yedekleme Kodları Kurulumu',
-    'mfa_gen_backup_codes_desc' => 'Store the below list of codes in a safe place. When accessing the system you\'ll be able to use one of the codes as a second authentication mechanism.',
+    'mfa_gen_backup_codes_desc' => 'Aşağıdaki kod listesini güvenli bir yerde sakla. Sisteme giriş yaparken kodlardan birini ikinci bir kimlik doğrulama mekanizması olarak kullanabileceksin.',
     'mfa_gen_backup_codes_download' => 'İndirme Kodları',
     'mfa_gen_backup_codes_usage_warning' => 'Her kod tek seferlik kullanılabilir',
     'mfa_gen_totp_title' => 'Mobil Uygulama Kurulumu',
-    'mfa_gen_totp_desc' => 'To use multi-factor authentication you\'ll need a mobile application that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.',
-    'mfa_gen_totp_scan' => 'Scan the QR code below using your preferred authentication app to get started.',
+    'mfa_gen_totp_desc' => 'Çok aşamalı kimlik doğrulamayı kullanabilmek için Google Authenticator, Authy veya Microsoft Authenticator gibi TOTP destekleyen bir mobil uygulamaya ihtiyacınız olacaktır.',
+    'mfa_gen_totp_scan' => 'Başlamak için aşağıdaki QR kodunu tercih ettiğin kimlik doğrulama uygulamasında tara.',
     'mfa_gen_totp_verify_setup' => 'Kurulumu Doğrula',
     'mfa_gen_totp_verify_setup_desc' => 'Aşağıdaki kutuya kimlik doğrulama uygulamanızda üretilmiş olan kodu girerek hepsini doğrulayabilirsiniz:',
     'mfa_gen_totp_provide_code_here' => 'Uygulamada üretilen kodunuzu buraya giriniz',
index 40b8591b3c03df45694a953dc10f208887cd2cf7..fe68799237789f4afbf23d01da49c520791f1198 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Önceki',
     'filter_active' => 'Aktif filtre:',
     'filter_clear' => 'Filtreyi Kaldır',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Sıralama Seçenekleri',
index f66a32f3d0121d6f54c67a2e2b43926068e820a7..f0bf6031254e441a5eaa0ddcb6f4f0c38e72076d 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Sayfa resim dosyalarının ikinci bir kopyası oluşturulmayıp, resimlerin ilk yüklendiği sayfadaki bağlantısı tutulacaktır.',
     'copy_consider_attachments' => 'Sayfa ekleri kopyalanmayacak.',
     'copy_consider_access' => 'Konum, sahiplik veya izinlerde yapılan bir değişiklik önceden erişimi olmayanlara erişim hakkı kazandırabilir.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 1d7efd66444f7046d21f8944006b235a2721d6b7..fbc78cdce1a05f6bd4879aed3093b44bc35f0537 100755 (executable)
@@ -27,7 +27,7 @@ return [
     '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_default_editor' => 'Default Page Editor',
+    'app_default_editor' => 'Varsayılan Yazı Düzenleyici',
     'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.',
     'app_custom_html' => 'Özel HTML "Head" İçeriği',
     'app_custom_html_desc' => 'Buraya yazacağınız içerik, <head> 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.',
@@ -152,7 +152,7 @@ return [
     'role_access_api' => 'Sistem programlama arayüzüne (API) eriş',
     'role_manage_settings' => 'Uygulama ayarlarını yönet',
     'role_export_content' => 'İçeriği dışa aktar',
-    'role_editor_change' => 'Change page editor',
+    'role_editor_change' => 'Yazı editörünü değiştir',
     'role_asset' => 'Varlık Yetkileri',
     'roles_system_warning' => 'Yukarıdaki üç izinden herhangi birine erişimin, kullanıcının kendi ayrıcalıklarını veya sistemdeki diğerlerinin ayrıcalıklarını değiştirmesine izin verebileceğini unutmayın. Yalnızca bu izinlere sahip rolleri güvenilir kullanıcılara atayın.',
     '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.',
index 470d1378170b16fb658a0a30f85c871496f9ff0a..7d024eb5005b3a8735085cad8f703a5db99aa1e4 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'створив книгу',
     'book_create_notification'    => 'Книгу успішно створено',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'оновив книгу',
     'book_update_notification'    => 'Книгу успішно оновлено',
     'book_delete'                 => 'видалив книгу',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'створив книжкову полицю',
     'bookshelf_create_notification'    => 'Книжкову полицю успішно створено',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'оновив книжкову полицю',
     'bookshelf_update_notification'    => 'Книжкову полицю успішно оновлено',
     'bookshelf_delete'                 => 'видалив книжкову полицю',
index ab6751498d7fe4a68a35d8cecc9b0d3d4aaf839e..b7d55ebeb286295249e97ea5843832be8d69846b 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Цей домен електронної пошти заборонений для реєстрації',
     'register_success' => 'Дякуємо за реєстрацію! Ви зареєстровані та ввійшли в систему.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Скинути пароль',
     'reset_password_send_instructions' => 'Введіть адресу електронної пошти нижче, і вам буде надіслано електронне повідомлення з посиланням на зміну пароля.',
index 13ef73e9dc9eacf6924ff075122f86029efd392b..549b22d11ac8f945cb5dedd005029282f43f0984 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Назад',
     'filter_active' => 'Активний фільтр:',
     'filter_clear' => 'Очистити фільтр',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Параметри сортування',
index bd9eadf1f99e52530c03b2c2646c4cad1a819525..fe0fff4258c7f9699b37fe70e19245c8466e5d50 100644 (file)
@@ -204,10 +204,10 @@ return [
     'pages_edit_enter_changelog_desc' => 'Введіть короткий опис внесених вами змін',
     'pages_edit_enter_changelog' => 'Введіть список змін',
     'pages_editor_switch_title' => 'Змінити редактор',
-    'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?',
-    'pages_editor_switch_consider_following' => 'Consider the following when changing editors:',
+    'pages_editor_switch_are_you_sure' => 'Ви впевнені, що хочете змінити редактор цієї сторінки?',
+    'pages_editor_switch_consider_following' => 'Врахуйте наступне при зміні редакторів:',
     'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.',
-    'pages_editor_switch_consideration_b' => 'This can potentially lead to a loss of detail and syntax in certain circumstances.',
+    'pages_editor_switch_consideration_b' => 'Це може потенційно призвести до втрати деталізації та синтаксису за певних обставин.',
     'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.',
     'pages_save' => 'Зберегти сторінку',
     'pages_title' => 'Заголовок сторінки',
@@ -235,7 +235,7 @@ return [
     'pages_revisions_number' => '#',
     'pages_revisions_numbered' => 'Версія #:id',
     'pages_revisions_numbered_changes' => 'Зміни версії #:id',
-    'pages_revisions_editor' => 'Editor Type',
+    'pages_revisions_editor' => 'Тип редактора',
     'pages_revisions_changelog' => 'Історія змін',
     'pages_revisions_changes' => 'Зміни',
     'pages_revisions_current' => 'Поточна версія',
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Файли зображень сторінки не будуть дубльовані і оригінальні зображення збережуть зв\'язок з сторінкою, до якої вони були завантажені.',
     'copy_consider_attachments' => 'Вкладення сторінки не буде скопійовано.',
     'copy_consider_access' => 'Зміна розташування або дозволів може призвести до доступу до цього вмісту без попереднього доступу.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index ae502a90346f6bd5760662b09cb17d0f8d4a9a69..85ab801f42b857d30045bc36c54350019b9fc525 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => 'yaratilgan kitob',
     'book_create_notification'    => 'Kitob muvaffaqiyatli yaratildi',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'yangilangan kitob',
     'book_update_notification'    => 'Kitob muvaffaqiyatli yangilandi',
     'book_delete'                 => 'o\'chirilgan kitob',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => 'yaratilgan kitobjavon',
     'bookshelf_create_notification'    => 'Kitobjavon muvaffaqiyatli yaratildi',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'yangilangan kitobjavob',
     'bookshelf_update_notification'    => 'Kitobjavon muvaffaqiyatli yangilandi',
     'bookshelf_delete'                 => 'o\'chirilgan kitobjavon',
index afe0f064cadbaf2b66a8f75ebe2d6eed03828763..08929d39d703803480bfe122204d7c6058b1b11f 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Ushbu domendagi email bilan ro\'yxatdan o\'tib bo\'lmaydi',
     'register_success' => 'Ro\'yxatdan o\'tganingiz uchun rahmat! Endi siz ushbu hisob bilan saytga kirishingiz mumkin.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => 'Parolni tiklash',
     'reset_password_send_instructions' => 'Parolni tiklash manzilini olish uchun emailingizni quyidagi maydonga kiriting.',
index 2f09e53d1fe88389e923863d875c43e8d2713d4a..703a70c7e6aa5bea2b59f7319d4739c5f7162c13 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => 'Previous',
     'filter_active' => 'Active Filter:',
     'filter_clear' => 'Clear Filter',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Sort Options',
index 18385594c18e1aac75bba00e2810de1c036e4836..3dd7ace47f6f362bf2daac9dd6dc2d9764bbaa50 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index ffbb33949550154dc5adff951efb1400c4a12357..eb51cd00edd346d29a8122c2c63abf064bd5b29d 100644 (file)
@@ -7,41 +7,45 @@ return [
 
     // Pages
     'page_create'                 => 'đã tạo trang',
-    'page_create_notification'    => 'Page successfully created',
+    'page_create_notification'    => 'Trang đã được tạo thành công',
     'page_update'                 => 'đã cập nhật trang',
-    'page_update_notification'    => 'Page successfully updated',
+    'page_update_notification'    => 'Trang đã được cập nhật thành công',
     'page_delete'                 => 'đã xóa trang',
-    'page_delete_notification'    => 'Page successfully deleted',
+    'page_delete_notification'    => 'Trang đã được xóa thành công',
     'page_restore'                => 'đã khôi phục trang',
-    'page_restore_notification'   => 'Page successfully restored',
+    'page_restore_notification'   => 'Trang đã được khôi phục thành công',
     'page_move'                   => 'đã di chuyển trang',
 
     // Chapters
     'chapter_create'              => 'đã tạo chương',
-    'chapter_create_notification' => 'Chapter successfully created',
+    'chapter_create_notification' => 'Chương đã được tạo thành công',
     'chapter_update'              => 'đã cập nhật chương',
-    'chapter_update_notification' => 'Chapter successfully updated',
+    'chapter_update_notification' => 'Chương đã được cập nhật thành công',
     'chapter_delete'              => 'đã xóa chương',
-    'chapter_delete_notification' => 'Chapter successfully deleted',
+    'chapter_delete_notification' => 'Chương đã được xóa thành công',
     'chapter_move'                => 'đã di chuyển chương',
 
     // Books
     'book_create'                 => 'đã tạo sách',
-    'book_create_notification'    => 'Book successfully created',
+    'book_create_notification'    => 'Sách đã được tạo thành công',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => 'đã cập nhật sách',
-    'book_update_notification'    => 'Book successfully updated',
+    'book_update_notification'    => 'Sách đã được cập nhật thành công',
     'book_delete'                 => 'đã xóa sách',
-    'book_delete_notification'    => 'Book successfully deleted',
+    'book_delete_notification'    => 'Sách đã được xóa thành công',
     'book_sort'                   => 'đã sắp xếp sách',
-    'book_sort_notification'      => 'Book successfully re-sorted',
+    'book_sort_notification'      => 'Sách đã được sắp xếp lại thành công',
 
     // Bookshelves
-    'bookshelf_create'            => 'created bookshelf',
-    'bookshelf_create_notification'    => 'Bookshelf successfully created',
+    'bookshelf_create'            => 'đã tạo giá sách',
+    'bookshelf_create_notification'    => 'Giá sách đã được tạo thành công',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => 'cập nhật giá sách',
-    'bookshelf_update_notification'    => 'Bookshelf successfully updated',
+    'bookshelf_update_notification'    => 'Giá sách đã được cập nhật thành công',
     'bookshelf_delete'                 => 'đã xóa giá sách',
-    'bookshelf_delete_notification'    => 'Bookshelf successfully deleted',
+    'bookshelf_delete_notification'    => 'Giá sách đã được xóa thành công',
 
     // Favourites
     'favourite_add_notification' => '":name" đã được thêm vào danh sách yêu thích của bạn',
@@ -52,16 +56,16 @@ return [
     'mfa_remove_method_notification' => 'Đã gỡ xác thực nhiều bước',
 
     // Webhooks
-    'webhook_create' => 'created webhook',
-    'webhook_create_notification' => 'Webhook successfully created',
-    'webhook_update' => 'updated webhook',
-    'webhook_update_notification' => 'Webhook successfully updated',
-    'webhook_delete' => 'deleted webhook',
-    'webhook_delete_notification' => 'Webhook successfully deleted',
+    'webhook_create' => 'đã tạo webhook',
+    'webhook_create_notification' => 'Webhook đã được tạo thành công',
+    'webhook_update' => 'đã cập nhật webhook',
+    'webhook_update_notification' => 'Webhook đã được cập nhật thành công',
+    'webhook_delete' => 'đã xóa webhook',
+    'webhook_delete_notification' => 'Webhook đã được xóa thành công',
 
     // Users
-    'user_update_notification' => 'User successfully updated',
-    'user_delete_notification' => 'User successfully removed',
+    'user_update_notification' => 'Người dùng được cập nhật thành công',
+    'user_delete_notification' => 'Người dùng đã được xóa thành công',
 
     // Other
     'commented_on'                => 'đã bình luận về',
index 63fe8b292d9e62667120e16b74ddd72f2b33ba17..0d63fb759b604bc045b264600d348c5e4b244d77 100644 (file)
@@ -21,7 +21,7 @@ return [
     'email' => 'Email',
     'password' => 'Mật khẩu',
     'password_confirm' => 'Xác nhận mật khẩu',
-    'password_hint' => 'Must be at least 8 characters',
+    'password_hint' => 'Phải có ít nhất 8 ký tự',
     'forgot_password' => 'Quên Mật khẩu?',
     'remember_me' => 'Ghi nhớ đăng nhập',
     'ldap_email_hint' => 'Vui lòng điền một địa chỉ email để sử dụng tài khoản này.',
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => 'Tên miền của email không có quyền truy cập tới ứng dụng này',
     'register_success' => 'Cảm ơn bạn đã đăng kí! Bạn đã được xác nhận và đăng nhập.',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     '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.',
@@ -54,7 +59,7 @@ return [
     'email_confirm_text' => 'Xin hãy xác nhận địa chỉa email bằng cách bấm vào nút dưới đây:',
     'email_confirm_action' => 'Xác nhận Email',
     'email_confirm_send_error' => 'Email xác nhận cần gửi nhưng hệ thống đã không thể gửi được email. Liên hệ với quản trị viên để chắc chắn email được thiết lập đúng.',
-    'email_confirm_success' => 'Your email has been confirmed! You should now be able to login using this email address.',
+    'email_confirm_success' => 'Email của bạn đã được xác nhận! Bạn có thể đăng nhập với email này ngay bây giờ.',
     'email_confirm_resent' => 'Email xác nhận đã được gửi lại, Vui lòng kiểm tra hộp thư.',
 
     'email_not_confirmed' => 'Địa chỉ email chưa được xác nhận',
@@ -71,7 +76,7 @@ return [
     'user_invite_page_welcome' => 'Chào mừng đến với :appName!',
     'user_invite_page_text' => 'Để hoàn tất tài khoản và lấy quyền truy cập bạn cần đặt mật khẩu để sử dụng cho các lần đăng nhập sắp tới tại :appName.',
     'user_invite_page_confirm_button' => 'Xác nhận Mật khẩu',
-    'user_invite_success_login' => 'Password set, you should now be able to login using your set password to access :appName!',
+    'user_invite_success_login' => 'Đã đặt mật khẩu, bạn có thể đăng nhập với mật khẩu trên để truy cập :appName!',
 
     // Multi-factor Authentication
     'mfa_setup' => 'Cài đặt xác thực nhiều bước',
@@ -80,14 +85,14 @@ return [
     'mfa_setup_reconfigure' => 'Cài đặt lại',
     'mfa_setup_remove_confirmation' => 'Bạn có chắc muốn gỡ bỏ phương thức xác thực nhiều bước này?',
     'mfa_setup_action' => 'Cài đặt',
-    'mfa_backup_codes_usage_limit_warning' => 'You have less than 5 backup codes remaining, Please generate and store a new set before you run out of codes to prevent being locked out of your account.',
+    'mfa_backup_codes_usage_limit_warning' => 'Bạn có ít hơn 5 mã dự phòng, Xin vui lòng tạo và lưu trữ bộ mã mới trước khi bạn dùng hết mã để tránh việc bị khóa quyền truy cập tài khoản.',
     'mfa_option_totp_title' => 'Ứng dụng di động',
-    'mfa_option_totp_desc' => 'To use multi-factor authentication you\'ll need a mobile application that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.',
+    'mfa_option_totp_desc' => 'Để sử dụng xác thực đa lớp bạn cần ưng dụng trên điện thoại có hỗ trợ TOTP như Google Authenticator, Authy hoặc Microsoft Authenticator.',
     'mfa_option_backup_codes_title' => 'Mã dự phòng',
-    'mfa_option_backup_codes_desc' => 'Securely store a set of one-time-use backup codes which you can enter to verify your identity.',
+    'mfa_option_backup_codes_desc' => 'Bảo mật việc lưu trữ mã dự phòng dùng một lần mà bạn có thể sử dụng để xác định danh tính của mình.',
     'mfa_gen_confirm_and_enable' => 'Xác nhận và Mở',
     'mfa_gen_backup_codes_title' => 'Cài đặt Mã dự phòng',
-    'mfa_gen_backup_codes_desc' => 'Store the below list of codes in a safe place. When accessing the system you\'ll be able to use one of the codes as a second authentication mechanism.',
+    'mfa_gen_backup_codes_desc' => 'Lưu trữ các mã dưới đây ở một nơi an toàn. Khi truy cập vào hệ thống bạn sẽ có thể sử dụng được một trong các đoạn mã đó như là một phương thức xác thực dự phòng.',
     'mfa_gen_backup_codes_download' => 'Tải mã',
     'mfa_gen_backup_codes_usage_warning' => 'Mỗi mã chỉ có thể sử dụng một lần',
     'mfa_gen_totp_title' => 'Cài đặt ứng dụng di động',
@@ -95,9 +100,9 @@ return [
     'mfa_gen_totp_scan' => 'Quét mã QR dưới đây bằng ứng dụng xác thực mà bạn muốn để bắt đầu.',
     'mfa_gen_totp_verify_setup' => 'Xác nhận cài đặt',
     'mfa_gen_totp_verify_setup_desc' => 'Xác nhận rằng tất cả hoạt động bằng cách nhập vào một mã, được tạo ra bởi ứng dụng xác thực của bạn vào ô dưới đây:',
-    'mfa_gen_totp_provide_code_here' => 'Provide your app generated code here',
+    'mfa_gen_totp_provide_code_here' => 'Cung cấp mã bạn tạo được từ ứng dụng ở đây',
     'mfa_verify_access' => 'Xác thực truy cập',
-    'mfa_verify_access_desc' => 'Your user account requires you to confirm your identity via an additional level of verification before you\'re granted access. Verify using one of your configured methods to continue.',
+    'mfa_verify_access_desc' => 'Tài khoản của bạn cần xác nhận danh tính của bạn thông qua một lớp xác thực bổ sung trước khi bạn được cấp quyền truy cập. Xác thực qua việc sử dụng một trong các phương thức để tiếp tục.',
     'mfa_verify_no_methods' => 'Không có phương pháp nào được cấu hình',
     'mfa_verify_no_methods_desc' => 'Tài khoản của bạn chưa đăng ký xác thực nhiều lớp. Bạn cần thiết lập ít nhất một phương pháp trước khi yêu cầu truy cập.',
     'mfa_verify_use_totp' => 'Xác thực sử dụng mã di động',
index 58447720e20c76fe78080ffa9e046552aa67bb75..23718b6b6d66c5da9278dcdbe34d0c12cc50aa34 100644 (file)
@@ -45,8 +45,10 @@ return [
     'unfavourite' => 'Bỏ yêu thích',
     'next' => 'Tiếp theo',
     'previous' => 'Trước đó',
-    'filter_active' => 'Active Filter:',
-    'filter_clear' => 'Clear Filter',
+    'filter_active' => 'Bộ lọc có hiệu lực:',
+    'filter_clear' => 'Xóa bộ lọc',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => 'Tùy Chọn Sắp Xếp',
@@ -71,14 +73,14 @@ return [
     'list_view' => 'Hiển thị dạng danh sách',
     'default' => 'Mặc định',
     'breadcrumb' => 'Đường dẫn liên kết',
-    'status' => 'Status',
-    'status_active' => 'Active',
-    'status_inactive' => 'Inactive',
-    'never' => 'Never',
-    'none' => 'None',
+    'status' => 'Trạng thái',
+    'status_active' => 'Hoạt động',
+    'status_inactive' => 'Không hoạt động',
+    'never' => 'Không bao giờ',
+    'none' => 'Không',
 
     // Header
-    'header_menu_expand' => 'Expand Header Menu',
+    'header_menu_expand' => 'Mở rộng Header Menu',
     'profile_menu' => 'Menu Hồ sơ',
     'view_profile' => 'Xem Hồ sơ',
     'edit_profile' => 'Sửa Hồ sơ',
index 52a4d4520def13e6b117d4b0ce0ccf4597b6b6c7..516273126cd220c8002a9c5ebf03d402e71c4957 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index ff1abbf8e545244edd89315f92d1facb9e0cfc6d..aff45258b75190a33794e8bb5de313d92b85c108 100644 (file)
@@ -23,10 +23,10 @@ return [
     'saml_no_email_address' => 'Không tìm thấy địa chỉ email cho người dùng này trong dữ liệu được cung cấp bới hệ thống xác thực ngoài',
     'saml_invalid_response_id' => 'Yêu cầu từ hệ thống xác thực bên ngoài không được nhận diện bởi quy trình chạy cho ứng dụng này. Điều hướng trở lại sau khi đăng nhập có thể đã gây ra vấn đề này.',
     'saml_fail_authed' => 'Đăng nhập sử dụng :system thất bại, hệ thống không cung cấp được sự xác thực thành công',
-    'oidc_already_logged_in' => 'Already logged in',
-    'oidc_user_not_registered' => 'The user :name is not registered and automatic registration is disabled',
-    'oidc_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system',
-    'oidc_fail_authed' => 'Login using :system failed, system did not provide successful authorization',
+    'oidc_already_logged_in' => 'Đã đăng nhập',
+    'oidc_user_not_registered' => 'Người dùng :name chưa được đăng ký và tự động đăng ký đang bị tắt',
+    'oidc_no_email_address' => 'Không tìm thấy địa chỉ email cho người dùng này, trong dữ liệu được cung cấp bới hệ thống xác thực ngoài',
+    'oidc_fail_authed' => 'Đăng nhập sử dụng :system thất bại, hệ thống không cung cấp được sự xác thực thành công',
     'social_no_action_defined' => 'Không có hành động được xác định',
     'social_login_bad_response' => "Xảy ra lỗi trong lúc đăng nhập :socialAccount: \n:error",
     'social_account_in_use' => 'Tài khoản :socialAccount này đang được sử dụng, Vui lòng thử đăng nhập bằng tùy chọn :socialAccount.',
index b4e0006873b48a23e25184c1719c524226e46c86..0c7992f7a943360abbe85a543d3a06f859db96db 100644 (file)
@@ -10,8 +10,8 @@ return [
     'settings' => 'Cài đặt',
     'settings_save' => 'Lưu Cài đặt',
     'settings_save_success' => 'Đã lưu cài đặt',
-    'system_version' => 'System Version',
-    'categories' => 'Categories',
+    'system_version' => 'Phiên bản Hệ thống',
+    'categories' => 'Danh mục',
 
     // App Settings
     'app_customization' => 'Tuỳ biến',
@@ -43,7 +43,7 @@ return [
     'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
     'app_footer_links_label' => 'Link Label',
     'app_footer_links_url' => 'Link URL',
-    'app_footer_links_add' => 'Add Footer Link',
+    'app_footer_links_add' => 'Thêm Footer Link',
     'app_disable_comments' => 'Tắt bình luận',
     'app_disable_comments_toggle' => 'Tắt bình luận',
     'app_disable_comments_desc' => 'Tắt các bình luận trên tất cả các trang của ứng dụng. <br> Các bình luận đã tồn tại sẽ không được hiển thị.',
@@ -236,17 +236,17 @@ return [
 
     // Webhooks
     'webhooks' => 'Webhooks',
-    'webhooks_create' => 'Create New Webhook',
-    'webhooks_none_created' => 'No webhooks have yet been created.',
-    'webhooks_edit' => 'Edit Webhook',
-    'webhooks_save' => 'Save Webhook',
-    'webhooks_details' => 'Webhook Details',
+    'webhooks_create' => 'Tạo Webhook mới',
+    'webhooks_none_created' => 'Chưa có webhooks nào được tạo.',
+    'webhooks_edit' => 'Chỉnh sửa Webhook',
+    'webhooks_save' => 'Lưu Webhook',
+    'webhooks_details' => 'Chi tiết Webhook',
     'webhooks_details_desc' => 'Provide a user friendly name and a POST endpoint as a location for the webhook data to be sent to.',
     'webhooks_events' => 'Webhook Events',
     'webhooks_events_desc' => 'Select all the events that should trigger this webhook to be called.',
     'webhooks_events_warning' => 'Keep in mind that these events will be triggered for all selected events, even if custom permissions are applied. Ensure that use of this webhook won\'t expose confidential content.',
     'webhooks_events_all' => 'All system events',
-    'webhooks_name' => 'Webhook Name',
+    'webhooks_name' => 'Tên Webhook',
     'webhooks_timeout' => 'Webhook Request Timeout (Seconds)',
     'webhooks_endpoint' => 'Webhook Endpoint',
     'webhooks_active' => 'Webhook Active',
@@ -256,10 +256,10 @@ return [
     'webhooks_delete_confirm' => 'Are you sure you want to delete this webhook?',
     'webhooks_format_example' => 'Webhook Format Example',
     'webhooks_format_example_desc' => 'Webhook data is sent as a POST request to the configured endpoint as JSON following the format below. The "related_item" and "url" properties are optional and will depend on the type of event triggered.',
-    'webhooks_status' => 'Webhook Status',
-    'webhooks_last_called' => 'Last Called:',
-    'webhooks_last_errored' => 'Last Errored:',
-    'webhooks_last_error_message' => 'Last Error Message:',
+    'webhooks_status' => 'Trạng thái Webhook',
+    'webhooks_last_called' => 'Lần cuối được gọi:',
+    'webhooks_last_errored' => 'Lần cuối xảy ra lỗi:',
+    'webhooks_last_error_message' => 'Nội dung lỗi gần nhất:',
 
 
     //! If editing translations files directly please ignore this in all
index c0985ec6975b8f24e5eaf6ad3e1b40ab6997b061..44e38eed9034070715f77b4f0f35976926c91202 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => '创建了图书',
     'book_create_notification'    => '图书已成功创建',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => '更新了图书',
     'book_update_notification'    => '图书已成功更新',
     'book_delete'                 => '删除了图书',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => '创建了书架',
     'bookshelf_create_notification'    => '书架已成功创建',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => '更新了书架',
     'bookshelf_update_notification'    => '书架已成功更新',
     'bookshelf_delete'                 => '删除了书架',
index 439d8aaee646a66caf0ad3af6400959db3694b19..2ce43af2a3bc959fd4a3c143b60d1140e7695b1e 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => '该Email域名无权访问此应用程序',
     'register_success' => '感谢您注册:appName,您现在已经登录。',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => '重置密码',
     'reset_password_send_instructions' => '在下面输入您的Email地址,您将收到一封带有密码重置链接的邮件。',
index ea62f2b976e503db645de9acfefdf0ac0634cb75..4889faf116c088d1609a6707f18b2ef7b3d7c5f3 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => '上一页',
     'filter_active' => '标签过滤器:',
     'filter_clear' => '清除过滤器',
+    'download' => '下载',
+    'open_in_tab' => '在标签页中打开。',
 
     // Sort Options
     'sort_options' => '排序选项',
index b4f439b68e055d2be9899277b8e1b85ec2d50107..6acc5c7a710e0027557692e7a09263572045c739 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => '页面中的图像文件不会被复制,原始图像将保留它们与最初上传到的页面的关系。',
     'copy_consider_attachments' => '页面中的附件不会被复制。',
     'copy_consider_access' => '改变位置、所有者或权限可能会导致此内容被以前无法访问的人访问。',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index 7a342919658c7ee1b565b196e622ff77c938e849..69639cbb6ecd1b7b0b404c5190501ec4b508f7d5 100644 (file)
@@ -28,6 +28,8 @@ return [
     // Books
     'book_create'                 => '已建立書本',
     'book_create_notification'    => '書本已建立成功',
+    'book_create_from_chapter'              => 'converted chapter to book',
+    'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
     'book_update'                 => '已更新書本',
     'book_update_notification'    => '書本已更新成功',
     'book_delete'                 => '已刪除書本',
@@ -38,6 +40,8 @@ return [
     // Bookshelves
     'bookshelf_create'            => '已建立書架',
     'bookshelf_create_notification'    => '書架已建立成功',
+    'bookshelf_create_from_book'    => 'converted book to bookshelf',
+    'bookshelf_create_from_book_notification'    => 'Book successfully converted to a shelf',
     'bookshelf_update'                 => '已更新書架',
     'bookshelf_update_notification'    => '書架已更新成功',
     'bookshelf_delete'                 => '已刪除書架',
index 4977d1ec2b74625e4aefad01ebc9ef380ce18fd2..d231ea54abc128d4f8c1cead763602b5f2bb8323 100644 (file)
@@ -38,6 +38,11 @@ return [
     'registration_email_domain_invalid' => '這個電子郵件網域沒有權限使用',
     'register_success' => '感謝您註冊!您已註冊完成並可登入。',
 
+    // Login auto-initiation
+    'auto_init_starting' => 'Attempting Login',
+    'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.',
+    'auto_init_start_link' => 'Proceed with authentication',
+
     // Password Reset
     'reset_password' => '重設密碼',
     'reset_password_send_instructions' => '在下方輸入您的電子郵件,您將收到一封帶有密碼重設連結的郵件。',
index ff1a80e2025cfde520e70c581ca96419e6b85cdb..ef768a08c891335963bb053a1adae34b96b581ba 100644 (file)
@@ -47,6 +47,8 @@ return [
     'previous' => '上一頁',
     'filter_active' => '使用中的過濾器',
     'filter_clear' => '清理過濾',
+    'download' => 'Download',
+    'open_in_tab' => 'Open in Tab',
 
     // Sort Options
     'sort_options' => '排序選項',
index a42946b990c3e8596796fd8acb11bb7b28174cab..19016fe1377983aca07161b80a7d234a21e24d4d 100644 (file)
@@ -355,4 +355,16 @@ return [
     'copy_consider_images' => 'Page image files will not be duplicated & the original images will retain their relation to the page they were originally uploaded to.',
     'copy_consider_attachments' => 'Page attachments will not be copied.',
     'copy_consider_access' => 'A change of location, owner or permissions may result in this content being accessible to those previously without access.',
+
+    // Conversions
+    'convert_to_shelf' => 'Convert to Shelf',
+    'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.',
+    'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.',
+    'convert_book' => 'Convert Book',
+    'convert_book_confirm' => 'Are you sure you want to convert this book?',
+    'convert_undo_warning' => 'This cannot be as easily undone.',
+    'convert_to_book' => 'Convert to Book',
+    'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
+    'convert_chapter' => 'Convert Chapter',
+    'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
 ];
index d03d5dc66274cfad9becfa7503c1245a5067506f..5fcc4bc338a75acfb6d951f6d75a8749ed686e53 100644 (file)
@@ -151,7 +151,7 @@ return [
     'role_manage_page_templates' => '管理頁面範本',
     'role_access_api' => '存取系統 API',
     'role_manage_settings' => '管理應用程式設定',
-    'role_export_content' => 'å\8c¯å\85¥內容',
+    'role_export_content' => 'å\8c¯å\87º內容',
     'role_editor_change' => 'Change page editor',
     'role_asset' => '資源權限',
     'roles_system_warning' => '請注意,有上述三項權限中的任一項的使用者都可以更改自己或系統中其他人的權限。有這些權限的角色只應分配給受信任的使用者。',
index 7d408cd1b5f24fdcb41f42e18e8b680bf9baa899..0398224ca52a406ee29d7ae160fa63a00caae4b4 100644 (file)
@@ -66,7 +66,6 @@
   @include lightDark(background-color, #FFF, #222);
   box-shadow: $bs-card;
   border-radius: 3px;
-  border: 1px solid transparent;
   .body, p.empty-text {
     padding: $-m;
   }
index 850443d9a7c02a500832990eaa0b9d4e7a7ca8d5..714dfc42c5905212c752a010489435774fecc79b 100644 (file)
@@ -99,6 +99,9 @@ button {
     fill: var(--color-primary);
   }
 }
+.text-button.hover-underline:hover {
+  text-decoration: underline;
+}
 
 .button.block {
   width: 100%;
index bce456cf2ce1e1b82147ae45e8f368ac83a91e83..4509c2b9a4b8a610e424eddfc54493d073b509a6 100644 (file)
@@ -1,3 +1,4 @@
+
 // System wide notifications
 [notification] {
   position: fixed;
@@ -61,7 +62,7 @@
   }
 }
 
-[chapter-toggle] {
+.chapter-contents-toggle {
   cursor: pointer;
   margin: 0;
   transition: all ease-in-out 180ms;
@@ -77,7 +78,7 @@
     transform: rotate(90deg);
   }
   svg[data-icon="caret-right"] + * {
-    margin-inline-start: $-xs;
+    margin-inline-start: $-xxs;
   }
 }
 
   }
 }
 
-.popup-footer button, .popup-header-close {
-  position: absolute;
-  top: 0;
-  right: 0;
+.popup-header button, .popup-footer button {
   margin: 0;
-  height: 40px;
   border-radius: 0;
   box-shadow: none;
-  &:active {
-    outline: 0;
+  color: #FFF;
+  padding: $-xs $-m;
+}
+
+.popup-header button:not(.popup-header-close) {
+  font-size: 0.8rem;
+}
+
+.popup-header button:hover {
+    background-color: rgba(255, 255, 255, 0.1);
+}
+
+.popup-footer {
+  justify-content: end;
+  background-color: var(--color-primary-light);
+  min-height: 41px;
+  button {
+    padding: 10px $-m;
   }
 }
+
 .popup-header-close {
-  background-color: transparent;
   border: 0;
   color: #FFF;
   font-size: 16px;
-  padding: 0 $-m;
+  cursor: pointer;
+  svg {
+    margin-right: 0;
+  }
 }
 
 .popup-header, .popup-footer {
-  display: block !important;
+  display: flex;
   position: relative;
   height: 40px;
-  flex: none !important;
+  flex: 0;
   .popup-title {
     color: #FFF;
+    margin-right: auto;
     padding: 8px $-m;
   }
+  &.flex-container-row {
+    display: flex !important;
+  }
 }
 body.flexbox-support #entity-selector-wrap .popup-body .form-group {
   height: 444px;
@@ -298,12 +318,6 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
   }
 }
 
-.image-manager .corner-button {
-  margin: 0;
-  border-radius: 0;
-  padding: $-m;
-}
-
 // Dropzone
 /*
  * The MIT License
@@ -630,24 +644,76 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
 }
 
 .code-editor .CodeMirror {
-  height: 400px;
+  height: auto;
+  min-height: 50vh;
+  border-bottom: 0;
 }
 
 .code-editor .lang-options {
-  max-width: 540px;
-  margin-bottom: $-s;
-  a {
-    margin-inline-end: $-xs;
-    text-decoration: underline;
+  overflow-y: scroll;
+  flex-basis: 200px;
+  flex-grow: 1;
+}
+
+.code-editor .lang-options button {
+  display: block;
+  padding: $-xs $-m;
+  border-bottom: 1px solid;
+  @include lightDark(color, #333, #AAA);
+  @include lightDark(border-bottom-color, #EEE, #000);
+  cursor: pointer;
+  width: 100%;
+  text-align: left;
+  font-family: $mono;
+  font-size: 0.7rem;
+  &:hover, &.active {
+    background-color: var(--color-primary-light);
+    color: var(--color-primary);
   }
 }
 
-@include smaller-than($m) {
-  .code-editor .lang-options {
+.code-editor label {
+  background-color: var(--color-primary-light);
+  width: 100%;
+  color: var(--color-primary);
+  padding: $-xxs $-m;
+  margin-bottom: 0;
+}
+
+.code-editor-language-list {
+  position: relative;
+  width: 160px;
+  z-index: 2;
+  align-items: stretch;
+}
+
+.code-editor-language-list input {
+  border-radius: 0;
+  border: 0;
+  border-bottom: 1px solid #DDD;
+  padding: $-xs $-m;
+}
+
+.code-editor-main {
+  flex: 1;
+  min-width: 0;
+  .CodeMirror {
+    margin-bottom: 0;
+    z-index: 1;
     max-width: 100%;
+    width: 100%;
+  }
+}
+
+@include smaller-than($s) {
+  .code-editor .lang-options {
+    display: none;
+  }
+  .code-editor-body-wrap {
+    flex-direction: column;
   }
-  .code-editor .CodeMirror {
-    height: 200px;
+  .code-editor-language-list, .code-editor-language-list input {
+    width: 100%;
   }
 }
 
@@ -731,6 +797,55 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
   }
 }
 
+
+.dropdown-search {
+  position: relative;
+}
+.dropdown-search-toggle-breadcrumb {
+  border: 1px solid transparent;
+  border-radius: 4px;
+  line-height: normal;
+  padding: $-xs;
+  &:hover {
+    border-color: #DDD;
+  }
+  .svg-icon {
+    margin-inline-end: 0;
+  }
+}
+.dropdown-search-toggle-select {
+  display: flex;
+  gap: $-s;
+  line-height: normal;
+  .svg-icon {
+    height: 16px;
+    margin: 0;
+  }
+  .avatar {
+    height: 22px;
+    width: 22px;
+  }
+  .avatar + span {
+    max-width: 100%;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .dropdown-search-toggle-caret {
+    font-size: 1.15rem;
+  }
+}
+.dropdown-search-toggle-select-label {
+  min-width: 0;
+  white-space: nowrap;
+}
+.dropdown-search-toggle-select-caret {
+  font-size: 1.5rem;
+  line-height: 0;
+  margin-left: auto;
+  margin-top: -2px;
+}
+
 .dropdown-search-dropdown {
   box-shadow: $bs-med;
   overflow: hidden;
@@ -739,7 +854,9 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
   display: none;
   position: absolute;
   z-index: 80;
-  right: -$-m;
+  right: 0;
+  top: 0;
+  margin-top: $-m;
   @include rtl {
     right: auto;
     left: -$-m;
@@ -767,12 +884,15 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
       text-decoration: none;
     }
   }
-  input {
+  input, input:focus {
     padding-inline-start: $-xl;
     border-radius: 0;
     border: 0;
     border-bottom: 1px solid #DDD;
   }
+  input:focus {
+    outline: 0;
+  }
 }
 
 @include smaller-than($m) {
@@ -784,10 +904,4 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
   .dropdown-search-dropdown .dropdown-search-list {
     max-height: 240px;
   }
-}
-
-.custom-select-input {
-  max-width: 280px;
-  border: 1px solid #D4D4D4;
-  border-radius: 3px;
 }
\ No newline at end of file
index 665b1213be8ba5a4401b3449c801f0c627d5c207..73799f0a03eaba71a5ad062e80b4a4c7a295c69f 100644 (file)
@@ -7,7 +7,8 @@
   @include lightDark(color, #666, #AAA);
   display: inline-block;
   font-size: $fs-m;
-  padding: $-xs*1.5;
+  padding: $-xs*1.8;
+  height: 40px;
   width: 250px;
   max-width: 100%;
 
@@ -350,16 +351,13 @@ input[type=color] {
   }
 }
 
-.inline-input-style {
+.title-input input[type="text"] {
   display: block;
   width: 100%;
   padding: $-s;
-}
-
-.title-input input[type="text"] {
-  @extend .inline-input-style;
   margin-top: 0;
   font-size: 2em;
+  height: auto;
 }
 
 .title-input.page-title {
@@ -373,6 +371,7 @@ input[type=color] {
     max-width: 840px;
     margin: 0 auto;
     border: none;
+    height: auto;
   }
 }
 
@@ -383,10 +382,12 @@ input[type=color] {
 }
 
 .description-input textarea {
-  @extend .inline-input-style;
+  display: block;
+  width: 100%;
+  padding: $-s;
   font-size: $fs-m;
   color: #666;
-  width: 100%;
+  height: auto;
 }
 
 div[editor-type="markdown"] .title-input.page-title input[type="text"] {
@@ -413,9 +414,11 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] {
   }
   input {
     display: block;
+    padding: $-xs * 1.5;
     padding-inline-start: $-l + 4px;
     width: 300px;
     max-width: 100%;
+    height: auto;
   }
   &.flexible input {
     width: 100%;
index f070f5a187428eedc0a2af37688733efa1af4a28..923f026c2663f3f9f09d301b89cb947c3c03188e 100644 (file)
@@ -21,19 +21,28 @@ header {
   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.8) brightness(0.8);
   }
+  .header-links {
+    display: flex;
+    align-items: center;
+    justify-content: end;
+  }
   .links {
     display: inline-block;
     vertical-align: top;
   }
   .links a {
     display: inline-block;
-    padding: $-m;
+    padding: 10px $-m;
     color: #FFF;
+    border-radius: 3px;
+  }
+  .links a:hover {
+    text-decoration: none;
+    background-color: rgba(255, 255, 255, .15);
   }
   .dropdown-container {
     padding-inline-start: $-m;
@@ -49,19 +58,25 @@ header {
   .user-name {
     vertical-align: top;
     position: relative;
-    display: inline-block;
+    display: inline-flex;
+    align-items: center;
     cursor: pointer;
-    > * {
-      vertical-align: top;
-    }
+    padding: $-s;
+    margin: 0 (-$-s);
+    border-radius: 3px;
+    gap: $-xs;
     > span {
       padding-inline-start: $-xs;
       display: inline-block;
-      padding-top: $-xxs;
+      line-height: 1;
     }
     > svg {
-      padding-top: 4px;
       font-size: 18px;
+      margin-top: -2px;
+      margin-inline-end: 0;
+    }
+    &:hover {
+      background-color: rgba(255, 255, 255, 0.15);
     }
     @include between($l, $xl) {
       padding-inline-start: $-xs;
@@ -79,22 +94,26 @@ header {
 
 header .search-box {
   display: inline-block;
-  margin-top: 10px;
   input {
     background-color: rgba(0, 0, 0, 0.2);
     border: 1px solid rgba(255, 255, 255, 0.2);
     border-radius: 40px;
     color: #EEE;
     z-index: 2;
+    height: auto;
+    padding: $-xs*1.5;
     padding-inline-start: 40px;
     &:focus {
       outline: none;
-      border: 1px solid rgba(255, 255, 255, 0.6);
+      border: 1px solid rgba(255, 255, 255, 0.4);
     }
   }
   button {
     z-index: 1;
     left: 16px;
+    top: 10px;
+    color: #FFF;
+    opacity: 0.6;
     @include lightDark(color, rgba(255, 255, 255, 0.8), #AAA);
     @include rtl {
       left: auto;
@@ -104,36 +123,39 @@ header .search-box {
       margin-block-end: 0;
     }
   }
-  ::-webkit-input-placeholder { /* Chrome/Opera/Safari */
-    color: #DDD;
-  }
-  ::-moz-placeholder { /* Firefox 19+ */
-    color: #DDD;
+  input::placeholder {
+    color: #FFF;
+    opacity: 0.6;
   }
   @include between($l, $xl) {
     max-width: 200px;
   }
+  &:focus-within button {
+    opacity: 1;
+  }
 }
 
 .logo {
-  display: inline-block;
+  display: inline-flex;
+  padding: ($-s - 6px) $-s;
+  margin: 6px (-$-s);
+  gap: $-s;
+  align-items: center;
+  border-radius: 4px;
   &:hover {
     color: #FFF;
     text-decoration: none;
+    background-color: rgba(255, 255, 255, .15);
   }
 }
+
 .logo-text {
-  display: inline-block;
   font-size: 1.8em;
   color: #fff;
   font-weight: 400;
-  @include padding(14px, $-l, 14px, 0);
-  vertical-align: top;
   line-height: 1;
 }
 .logo-image {
-  @include margin($-xs, $-s, $-xs, 0);
-  vertical-align: top;
   height: 43px;
 }
 
@@ -172,23 +194,29 @@ header .search-box {
     overflow: hidden;
     position: absolute;
     box-shadow: $bs-hover;
-    margin-top: -$-xs;
+    margin-top: $-m;
+    padding: $-xs 0;
     &.show {
       display: block;
     }
   }
   header .links a, header .dropdown-container ul li a, header .dropdown-container ul li button {
     text-align: start;
-    display: block;
-    padding: $-s $-m;
+    display: grid;
+    align-items: center;
+    padding: 8px $-m;
+    gap: $-m;
     color: $text-dark;
+    grid-template-columns: 16px auto;
+    line-height: 1.4;
     @include lightDark(color, $text-dark, #eee);
     svg {
       margin-inline-end: $-s;
+      width: 16px;
     }
     &:hover {
-      @include lightDark(background-color, #eee, #333);
-      @include lightDark(color, #000, #fff);
+      background-color: var(--color-primary-light);
+      color: var(--color-primary);
       text-decoration: none;
     }
     &:focus {
@@ -279,29 +307,6 @@ header .search-box {
   }
 }
 
-.dropdown-search {
-  position: relative;
-  .dropdown-search-toggle {
-    padding: $-xs;
-    border: 1px solid transparent;
-    border-radius: 4px;
-    &:hover {
-      border-color: #DDD;
-    }
-  }
-  .svg-icon {
-    margin-inline-end: 0;
-  }
-}
-
-.dropdown-search-toggle.compact {
-  padding: $-xxs $-xs;
-  .avatar {
-    height: 22px;
-    width: 22px;
-  }
-}
-
 .faded {
   a, button, span, span > div {
     color: #666;
index b1c80cb53eb7e95b3e3d3ceb023392ffad54a644..14a37dd4a2465777572e7787695d69ac690f1e26 100644 (file)
@@ -155,6 +155,13 @@ body.flexbox {
   }
 }
 
+.gap-m {
+  gap: $-m;
+}
+
+.justify-flex-start {
+  justify-content: flex-start;
+}
 .justify-flex-end {
   justify-content: flex-end;
 }
@@ -295,9 +302,9 @@ body.flexbox {
 }
 @include larger-than($xxl) {
   .tri-layout-left-contents, .tri-layout-right-contents {
-    padding: $-m;
+    padding: $-xl $-m;
     position: sticky;
-    top: $-m;
+    top: 0;
     max-height: 100vh;
     min-height: 50vh;
     overflow-y: scroll;
index 26d12a25da42949cbced533fd25ac66caac1bf9c..19060fbbf5d3b02e0129656b40f6d5ccd94d46fe 100644 (file)
@@ -6,7 +6,7 @@
     justify-self: stretch;
     align-self: stretch;
     height: auto;
-    margin-inline-end: $-l;
+    margin-inline-end: $-xs;
   }
   .icon:after {
     opacity: 0.5;
   > .content {
     flex: 1;
   }
-  .chapter-expansion-toggle {
+  .chapter-contents-toggle {
     border-radius: 0 4px 4px 0;
-    padding: $-xs $-m;
+    padding: $-xs ($-m + $-xxs);
     width: 100%;
     text-align: start;
   }
-  .chapter-expansion-toggle:hover {
+  .chapter-contents-toggle:hover {
     background-color: rgba(0, 0, 0, 0.06);
   }
 }
   @include margin($-xs, -$-s, 0, -$-s);
   padding-inline-start: 0;
   padding-inline-end: 0;
-  position: relative;
-
-  &:after, .sub-menu:after {
-    content: '';
-    display: block;
-    position: absolute;
-    left: $-m;
-    top: 1rem;
-    bottom: 1rem;
-    border-inline-start: 4px solid rgba(0, 0, 0, 0.1);
-    z-index: 0;
-    @include rtl {
-      left: auto;
-      right: $-m;
-    }
-  }
 
   ul {
     list-style: none;
   }
 
   .entity-list-item {
-    padding-top: $-xxs;
-    padding-bottom: $-xxs;
+    padding-top: 2px;
+    padding-bottom: 2px;
     background-clip: content-box;
     border-radius: 0 3px 3px 0;
     padding-inline-end: 0;
     .content {
+      width: 100%;
       padding-top: $-xs;
       padding-bottom: $-xs;
       max-width: calc(100% - 20px);
     }
   }
   .entity-list-item.selected {
-    @include lightDark(background-color, rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.08));
+    @include lightDark(background-color, rgba(0, 0, 0, 0.06), rgba(255, 255, 255, 0.06));
   }
   .entity-list-item.no-hover {
     margin-top: -$-xs;
     margin-top: -.2rem;
     margin-inline-start: -1rem;
   }
-  [chapter-toggle] {
-    padding-inline-start: .7rem;
-    padding-bottom: .2rem;
+  .chapter-contents-toggle {
+    display: block;
+    width: 100%;
+    text-align: left;
+    padding: $-xxs $-s ($-xxs * 2) $-s;
+    border-radius: 0 3px 3px 0;
+    line-height: 1;
+    margin-top: -$-xxs;
+    margin-bottom: -$-xxs;
+    &:hover {
+      @include lightDark(background-color, rgba(0, 0, 0, 0.06), rgba(255, 255, 255, 0.06));
+    }
   }
   .entity-list-item .icon {
     z-index: 2;
     align-self: stretch;
     flex-shrink: 0;
     border-radius: 1px;
-    opacity: 0.6;
+    opacity: 0.8;
   }
   .entity-list-item .icon:after {
     opacity: 1;
   }
 }
 
-.chapter-child-menu {
-  ul.sub-menu {
-    display: none;
-    padding-inline-start: 0;
-    position: relative;
-  }
-  [chapter-toggle].open + .sub-menu {
-    display: block;
-  }
+.chapter-child-menu ul.sub-menu {
+  display: none;
+  padding-inline-start: 0;
+  position: relative;
+  margin-bottom: 0;
 }
 
 // Sortable Lists
@@ -415,6 +405,7 @@ ul.pagination {
   padding: $-s $-m;
   display: flex;
   align-items: center;
+  gap: $-m;
   background-color: transparent;
   border: 0;
   width: 100%;
@@ -424,7 +415,6 @@ ul.pagination {
     color: #666;
   }
   > span:first-child {
-    margin-inline-end: $-m;
     flex-basis: 1.88em;
     flex: none;
   }
@@ -439,8 +429,8 @@ ul.pagination {
     cursor: pointer;
   }
   &:not(.no-hover):hover {
+    @include lightDark(background-color, rgba(0, 0, 0, 0.06), rgba(255, 255, 255, 0.06));
     text-decoration: none;
-    background-color: rgba(0, 0, 0, 0.1);
     border-radius: 4px;
   }
   &.outline-hover:hover {
@@ -463,19 +453,74 @@ ul.pagination {
   }
 }
 
-.card .entity-list-item:not(.no-hover):hover {
-  @include lightDark(background-color, #F2F2F2, #2d2d2d)
+.split-icon-list-item {
+  display: flex;
+  align-items: center;
+  gap: $-m;
+  background-color: transparent;
+  border: 0;
+  width: 100%;
+  position: relative;
+  word-break: break-word;
+  border-radius: 4px;
+  > a {
+    padding: $-s $-m;
+    display: flex;
+    align-items: center;
+    gap: $-m;
+    flex: 1;
+  }
+  > a:hover {
+    text-decoration: none;
+  }
+  .icon {
+    flex-basis: 1.88em;
+    flex: none;
+  }
+  &:hover {
+    @include lightDark(background-color, rgba(0, 0, 0, 0.06), rgba(255, 255, 255, 0.06));
+  }
+}
+
+.icon-list-item-dropdown {
+  margin-inline-start: auto;
+  align-self: stretch;
+  display: flex;
+  align-items: stretch;
+  border-inline-start: 1px solid rgba(0, 0, 0, .1);
+  visibility: hidden;
+}
+.split-icon-list-item:hover .icon-list-item-dropdown,
+.split-icon-list-item:focus-within .icon-list-item-dropdown {
+  visibility: visible;
+}
+.icon-list-item-dropdown-toggle {
+  padding: $-xs;
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+  @include lightDark(color, #888, #999);
+  svg {
+    margin: 0;
+  }
+  &:hover {
+    @include lightDark(background-color, rgba(0, 0, 0, 0.06), rgba(255, 255, 255, 0.06));
+  }
+}
+
+.card .entity-list-item:not(.no-hover, .book-contents .entity-list-item):hover {
+  @include lightDark(background-color, #F2F2F2, #2d2d2d);
+  border-radius: 0;
 }
 .card .entity-list-item .entity-list-item:hover {
   background-color: #EEEEEE;
 }
 
 .entity-list-item-children {
-  padding: $-m;
+  padding: $-m $-l;
   > div {
     overflow: hidden;
-    padding: $-xs 0;
-    margin-top: -$-xs;
+    padding: 0 0 $-xs 0;
   }
   .entity-chip {
     text-overflow: ellipsis;
@@ -485,6 +530,9 @@ ul.pagination {
     display: block;
     white-space: nowrap;
   }
+  > .entity-list > .entity-list-item:last-child {
+    margin-bottom: -$-xs;
+  }
 }
 
 .entity-list-item-image {
@@ -531,6 +579,9 @@ ul.pagination {
     font-size: $fs-m * 0.8;
     padding-top: $-xs;
   }
+  .entity-list-item p:empty {
+    padding-top: 0;
+  }
   p {
     margin: 0;
   }
@@ -574,8 +625,8 @@ ul.pagination {
   right: 0;
   margin: $-m 0;
   @include lightDark(background-color, #fff, #333);
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
-  border-radius: 1px;
+  box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.18);
+  border-radius: 3px;
   min-width: 180px;
   padding: $-xs 0;
   @include lightDark(color, #555, #eee);
@@ -652,6 +703,13 @@ ul.pagination {
   }
 }
 
+// Shift in sidebar dropdown menus to prevent shadows
+// being cut by scrollable container.
+.tri-layout-right .dropdown-menu,
+.tri-layout-left .dropdown-menu {
+  right: $-xs;
+}
+
 // Books grid view
 .featured-image-container {
   position: relative;
@@ -719,3 +777,19 @@ ul.pagination {
     }
   }
 }
+
+.entity-meta-item {
+  display: flex;
+  line-height: 1.2;
+  margin: 0.6em 0;
+  align-content: start;
+  gap: $-s;
+  a {
+    line-height: 1.2;
+  }
+  svg {
+    flex-shrink: 0;
+    width: 1em;
+    margin: 0;
+  }
+}
index 73819975fb6150fb9ffd66354f93a665416b533d..3ceec61d091245ada86bc0f81c6dbcd5f02fa8df 100755 (executable)
@@ -396,10 +396,14 @@ body.tox-fullscreen, body.markdown-fullscreen {
   }
 }
 
-.entity-list-item > span:first-child, .icon-list-item > span:first-child, .chapter-expansion > .icon {
+.entity-list-item > span:first-child,
+.icon-list-item > span:first-child,
+.split-icon-list-item > a > .icon,
+.chapter-expansion > .icon {
   font-size: 0.8rem;
   width: 1.88em;
   height: 1.88em;
+  flex-shrink: 0;
   display: flex;
   align-items: center;
   justify-content: center;
index 1a8b34c5b9af119865929d1eebde78c8180d2a99..b8160b4c2df575e594b347b0e811dbf8a425fe4b 100644 (file)
@@ -59,4 +59,47 @@ ul.contents ul li {
 }
 .chapter-hint + h1 {
   margin-top: 0;
+}
+
+// PDF specific overrides
+body.export-format-pdf {
+  font-size: 14px;
+  line-height: 1.2;
+
+  h1, h2, h3, h4, h5, h6 {
+    line-height: 1.2;
+  }
+
+  table {
+    max-width: 800px !important;
+    font-size: 0.8em;
+    width: 100% !important;
+  }
+
+  table td {
+    width: auto !important;
+  }
+
+  .page-content .float {
+    float: none !important;
+  }
+
+  .page-content img.align-left, .page-content img.align-right  {
+    float: none !important;
+    clear: both;
+    display: block;
+  }
+
+}
+
+// DOMPDF pdf export specific overrides
+body.export-format-pdf.export-engine-dompdf {
+  // Fix for full width linked image sizes on DOMPDF
+  .page-content a > img {
+    max-width: 700px;
+  }
+  // Undoes the above for table images to prevent visually worse scenario, Awaiting next DOMPDF release for patch
+  .page-content td a > img {
+    max-width: 100%;
+  }
 }
\ No newline at end of file
index 582bf7c7569a7faa4a55b7fc1d159e31cd490db6..ee99d76682c7edf1b8601bc037d0d5f033f2bfc4 100644 (file)
@@ -79,17 +79,17 @@ $loadingSize: 10px;
     animation-timing-function: cubic-bezier(.62, .28, .23, .99);
     margin-inline-end: 4px;
     background-color: var(--color-page);
-    animation-delay: 0.3s;
+    animation-delay: -300ms;
   }
   > div:first-child {
       left: -($loadingSize+$-xs);
       background-color: var(--color-book);
-      animation-delay: 0s;
+      animation-delay: -600ms;
   }
   > div:last-of-type {
     left: $loadingSize+$-xs;
     background-color: var(--color-chapter);
-    animation-delay: 0.6s;
+    animation-delay: 0ms;
   }
   > span {
     margin-inline-start: $-s;
@@ -138,7 +138,7 @@ $btt-size: 40px;
 
 .skip-to-content-link {
   position: fixed;
-  top: -$-xxl;
+  top: -52px;
   left: 0;
   background-color: #FFF;
   z-index: 15;
index f0a1354ea1e513adda8ad44b1c8e03ed63c0a2a2..a6ffb709b4dc097ecf4b14d0785aa7e585b77e94 100644 (file)
@@ -1,10 +1,27 @@
 <div component="attachments-list">
     @foreach($attachments as $attachment)
         <div class="attachment icon-list">
-            <a class="icon-list-item py-xs attachment-{{ $attachment->external ? 'link' : 'file' }}" href="{{ $attachment->getUrl() }}" @if($attachment->external) target="_blank" @endif>
-                <span class="icon">@icon($attachment->external ? 'export' : 'file')</span>
-                <span>{{ $attachment->name }}</span>
-            </a>
+            <div class="split-icon-list-item attachment-{{ $attachment->external ? 'link' : 'file' }}">
+                <a href="{{ $attachment->getUrl() }}" @if($attachment->external) target="_blank" @endif>
+                    <div class="icon">@icon($attachment->external ? 'export' : 'file')</div>
+                    <div class="label">{{ $attachment->name }}</div>
+                </a>
+                @if(!$attachment->external)
+                    <div component="dropdown" class="icon-list-item-dropdown">
+                        <button refs="dropdown@toggle" type="button" class="icon-list-item-dropdown-toggle">@icon('caret-down')</button>
+                        <ul refs="dropdown@menu" class="dropdown-menu" role="menu">
+                            <a href="{{ $attachment->getUrl(false) }}" class="icon-item">
+                                @icon('download')
+                                <div>{{ trans('common.download') }}</div>
+                            </a>
+                            <a href="{{ $attachment->getUrl(true) }}" target="_blank" class="icon-item">
+                                @icon('export')
+                                <div>{{ trans('common.open_in_tab') }}</div>
+                            </a>
+                        </ul>
+                    </div>
+                @endif
+            </div>
         </div>
     @endforeach
 </div>
\ No newline at end of file
diff --git a/resources/views/auth/login-initiate.blade.php b/resources/views/auth/login-initiate.blade.php
new file mode 100644 (file)
index 0000000..520175f
--- /dev/null
@@ -0,0 +1,37 @@
+@extends('layouts.simple')
+
+@section('content')
+
+    <div class="container very-small">
+
+        <div class="my-l">&nbsp;</div>
+
+        <div class="card content-wrap auto-height">
+            <h1 class="list-heading">{{ trans('auth.auto_init_starting') }}</h1>
+
+            <div style="display:none">
+                @include('auth.parts.login-form-' . $authMethod)
+            </div>
+
+            <div class="grid half left-focus">
+                <div>
+                    <p class="text-small">{{ trans('auth.auto_init_starting_desc') }}</p>
+                    <p>
+                        <button type="submit" form="login-form" class="p-none text-button hover-underline">
+                            {{ trans('auth.auto_init_start_link') }}
+                        </button>
+                    </p>
+                </div>
+                <div class="text-center">
+                    @include('common.loading-icon')
+                </div>
+            </div>
+
+            <script nonce="{{ $cspNonce }}">
+                window.addEventListener('load', () => document.forms['login-form'].submit());
+            </script>
+
+        </div>
+    </div>
+
+@stop
index 4039771213d49e57d9d6e9924c00b67ebee25c8e..180500e0a04ae737b1f86668d7f8a41c070919e9 100644 (file)
             ]])
         </div>
 
-        <main class="content-wrap card">
+        <main class="content-wrap card auto-height">
             <h1 class="list-heading">{{ trans('entities.books_edit') }}</h1>
             <form action="{{ $book->getUrl() }}" method="POST" enctype="multipart/form-data">
                 <input type="hidden" name="_method" value="PUT">
                 @include('books.parts.form', ['model' => $book, 'returnLocation' => $book->getUrl()])
             </form>
         </main>
+
+
+        @if(userCan('book-delete', $book) && userCan('book-create-all') && userCan('bookshelf-create-all'))
+            @include('books.parts.convert-to-shelf', ['book' => $book])
+        @endif
     </div>
 @stop
\ No newline at end of file
diff --git a/resources/views/books/export.blade.php b/resources/views/books/export.blade.php
deleted file mode 100644 (file)
index 0b6b4a5..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-@extends('layouts.export')
-
-@section('title', $book->name)
-
-@section('content')
-    <h1 style="font-size: 4.8em">{{$book->name}}</h1>
-
-    <p>{{ $book->description }}</p>
-
-    @if(count($bookChildren) > 0)
-        <ul class="contents">
-            @foreach($bookChildren as $bookChild)
-                <li><a href="#{{$bookChild->getType()}}-{{$bookChild->id}}">{{ $bookChild->name }}</a></li>
-                @if($bookChild->isA('chapter') && count($bookChild->visible_pages) > 0)
-                    <ul>
-                        @foreach($bookChild->visible_pages as $page)
-                            <li><a href="#page-{{$page->id}}">{{ $page->name }}</a></li>
-                        @endforeach
-                    </ul>
-                @endif
-            @endforeach
-        </ul>
-    @endif
-
-    @foreach($bookChildren as $bookChild)
-        <div class="page-break"></div>
-        <h1 id="{{$bookChild->getType()}}-{{$bookChild->id}}">{{ $bookChild->name }}</h1>
-
-        @if($bookChild->isA('chapter'))
-            <p>{{ $bookChild->description }}</p>
-
-            @if(count($bookChild->visible_pages) > 0)
-                @foreach($bookChild->visible_pages as $page)
-                    <div class="page-break"></div>
-                    <div class="chapter-hint">{{$bookChild->name}}</div>
-                    <h1 id="page-{{$page->id}}">{{ $page->name }}</h1>
-                    {!! $page->html !!}
-                @endforeach
-            @endif
-
-        @else
-            {!! $bookChild->html !!}
-        @endif
-
-    @endforeach
-@endsection
\ No newline at end of file
diff --git a/resources/views/books/parts/convert-to-shelf.blade.php b/resources/views/books/parts/convert-to-shelf.blade.php
new file mode 100644 (file)
index 0000000..dde60aa
--- /dev/null
@@ -0,0 +1,26 @@
+<div class="content-wrap card auto-height">
+    <h2 class="list-heading">{{ trans('entities.convert_to_shelf') }}</h2>
+    <p>
+        {{ trans('entities.convert_to_shelf_contents_desc') }}
+        <br><br>
+        {{ trans('entities.convert_to_shelf_permissions_desc') }}
+    </p>
+    <div class="text-right">
+        <div component="dropdown" class="dropdown-container">
+            <button refs="dropdown@toggle" class="button outline" aria-haspopup="true" aria-expanded="false">{{ trans('entities.convert_book') }}</button>
+            <ul refs="dropdown@menu" class="dropdown-menu" role="menu">
+                <li class="px-m py-s text-small text-muted">
+                    {{ trans('entities.convert_book_confirm') }}
+                    <br>
+                    {{ trans('entities.convert_undo_warning') }}
+                </li>
+                <li>
+                    <form action="{{ $book->getUrl('/convert-to-shelf') }}" method="POST">
+                        {!! csrf_field() !!}
+                        <button type="submit" class="text-primary text-item">{{ trans('common.confirm') }}</button>
+                    </form>
+                </li>
+            </ul>
+        </div>
+    </div>
+</div>
\ No newline at end of file
index 5263bc8101007d6196a1f9bff34dc462d490e7e0..e0cb4b862dd8327179c4b1655f6d574d1886c36f 100644 (file)
 @section('right')
     <div class="mb-xl">
         <h5>{{ trans('common.details') }}</h5>
-        <div class="text-small text-muted blended-links">
+        <div class="blended-links">
             @include('entities.meta', ['entity' => $book])
             @if($book->restricted)
                 <div class="active-restriction">
                     @if(userCan('restrictions-manage', $book))
-                        <a href="{{ $book->getUrl('/permissions') }}">@icon('lock'){{ trans('entities.books_permissions_active') }}</a>
+                        <a href="{{ $book->getUrl('/permissions') }}" class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.books_permissions_active') }}</div>
+                        </a>
                     @else
-                        @icon('lock'){{ trans('entities.books_permissions_active') }}
+                        <div class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.books_permissions_active') }}</div>
+                        </div>
                     @endif
                 </div>
             @endif
index 65c48c18d77aba368a7af0872ad273d672e764a2..36058eff83bb090428133cb1a13744f5e6fa7646 100644 (file)
@@ -15,7 +15,7 @@
             ]])
         </div>
 
-        <main class="content-wrap card">
+        <main class="content-wrap card auto-height">
             <h1 class="list-heading">{{ trans('entities.chapters_edit') }}</h1>
             <form action="{{  $chapter->getUrl() }}" method="POST">
                 <input type="hidden" name="_method" value="PUT">
             </form>
         </main>
 
+        @if(userCan('chapter-delete', $chapter) && userCan('book-create-all'))
+            @include('chapters.parts.convert-to-book')
+        @endif
+
     </div>
 
 @stop
\ No newline at end of file
diff --git a/resources/views/chapters/export.blade.php b/resources/views/chapters/export.blade.php
deleted file mode 100644 (file)
index 61286ab..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-@extends('layouts.export')
-
-@section('title', $chapter->name)
-
-@section('content')
-    <h1 style="font-size: 4.8em">{{$chapter->name}}</h1>
-
-    <p>{{ $chapter->description }}</p>
-
-    @if(count($pages) > 0)
-        <ul class="contents">
-            @foreach($pages as $page)
-                <li><a href="#page-{{$page->id}}">{{ $page->name }}</a></li>
-            @endforeach
-        </ul>
-    @endif
-
-    @foreach($pages as $page)
-        <div class="page-break"></div>
-        <h1 id="page-{{$page->id}}">{{ $page->name }}</h1>
-        {!! $page->html !!}
-    @endforeach
-@endsection
\ No newline at end of file
index a00f0f7e1ae341c3a6638fe091c153118e7c9baf..8fdd091437beacdaca563b2330601b008f3bbc1d 100644 (file)
@@ -1,9 +1,14 @@
-<div class="chapter-child-menu">
-    <button chapter-toggle type="button" aria-expanded="{{ $isOpen ? 'true' : 'false' }}"
-            class="text-muted @if($isOpen) open @endif">
+<div component="chapter-contents" class="chapter-child-menu">
+    <button type="button"
+            refs="chapter-contents@toggle"
+            aria-expanded="{{ $isOpen ? 'true' : 'false' }}"
+            class="text-muted chapter-contents-toggle @if($isOpen) open @endif">
         @icon('caret-right') @icon('page') <span>{{ trans_choice('entities.x_pages', $bookChild->visible_pages->count()) }}</span>
     </button>
-    <ul class="sub-menu inset-list @if($isOpen) open @endif" @if($isOpen) style="display: block;" @endif role="menu">
+    <ul refs="chapter-contents@list"
+        class="chapter-contents-list sub-menu inset-list @if($isOpen) open @endif" @if($isOpen)
+        style="display: block;" @endif
+        role="menu">
         @foreach($bookChild->visible_pages as $childPage)
             <li class="list-item-page {{ $childPage->isA('page') && $childPage->draft ? 'draft' : '' }}" role="presentation">
                 @include('entities.list-item-basic', ['entity' => $childPage, 'classes' => $current->matches($childPage)? 'selected' : '' ])
diff --git a/resources/views/chapters/parts/convert-to-book.blade.php b/resources/views/chapters/parts/convert-to-book.blade.php
new file mode 100644 (file)
index 0000000..516d111
--- /dev/null
@@ -0,0 +1,28 @@
+<div class="content-wrap card auto-height">
+    <h2 class="list-heading">{{ trans('entities.convert_to_book') }}</h2>
+    <div class="grid half left-focus no-row-gap">
+        <p>
+            {{ trans('entities.convert_to_book_desc') }}
+        </p>
+        <div class="text-m-right">
+            <div component="dropdown" class="dropdown-container">
+                <button refs="dropdown@toggle" class="button outline" aria-haspopup="true" aria-expanded="false">
+                    {{ trans('entities.convert_chapter') }}
+                </button>
+                <ul refs="dropdown@menu" class="dropdown-menu" role="menu">
+                    <li class="px-m py-s text-small text-muted">
+                        {{ trans('entities.convert_chapter_confirm') }}
+                        <br>
+                        {{ trans('entities.convert_undo_warning') }}
+                    </li>
+                    <li>
+                        <form action="{{ $chapter->getUrl('/convert-to-book') }}" method="POST">
+                            {!! csrf_field() !!}
+                            <button type="submit" class="text-primary text-item">{{ trans('common.confirm') }}</button>
+                        </form>
+                    </li>
+                </ul>
+            </div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
index 285e3489353cca255481e32241245f856527aae0..c3e735e2bfc43c703f8f80f885c92c238a3e24d1 100644 (file)
@@ -5,18 +5,19 @@
     <div class="content">
         <h4 class="entity-list-item-name break-text">{{ $chapter->name }}</h4>
         <div class="entity-item-snippet">
-            <p class="text-muted break-text mb-s">{{ $chapter->getExcerpt() }}</p>
+            <p class="text-muted break-text">{{ $chapter->getExcerpt() }}</p>
         </div>
     </div>
 </a>
 @if ($chapter->visible_pages->count() > 0)
     <div class="chapter chapter-expansion">
         <span class="icon text-chapter">@icon('page')</span>
-        <div class="content">
-            <button type="button" chapter-toggle
+        <div component="chapter-contents" class="content">
+            <button type="button"
+                    refs="chapter-contents@toggle"
                     aria-expanded="false"
-                    class="text-muted chapter-expansion-toggle">@icon('caret-right') <span>{{ trans_choice('entities.x_pages', $chapter->visible_pages->count()) }}</span></button>
-            <div class="inset-list">
+                    class="text-muted chapter-contents-toggle">@icon('caret-right') <span>{{ trans_choice('entities.x_pages', $chapter->visible_pages->count()) }}</span></button>
+            <div refs="chapter-contents@list" class="inset-list chapter-contents-list">
                 <div class="entity-list-item-children">
                     @include('entities.list', ['entities' => $chapter->visible_pages])
                 </div>
index edd39eddebed863b45c55b95396adfaae6a9880a..3e015616ad34384e1cf0f633543f4785e4d86844 100644 (file)
 
     <div class="mb-xl">
         <h5>{{ trans('common.details') }}</h5>
-        <div class="blended-links text-small text-muted">
+        <div class="blended-links">
             @include('entities.meta', ['entity' => $chapter])
 
             @if($book->restricted)
                 <div class="active-restriction">
                     @if(userCan('restrictions-manage', $book))
-                        <a href="{{ $book->getUrl('/permissions') }}">@icon('lock'){{ trans('entities.books_permissions_active') }}</a>
+                        <a href="{{ $book->getUrl('/permissions') }}" class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.books_permissions_active') }}</div>
+                        </a>
                     @else
-                        @icon('lock'){{ trans('entities.books_permissions_active') }}
+                        <div class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.books_permissions_active') }}</div>
+                        </div>
                     @endif
                 </div>
             @endif
             @if($chapter->restricted)
                 <div class="active-restriction">
                     @if(userCan('restrictions-manage', $chapter))
-                        <a href="{{ $chapter->getUrl('/permissions') }}">@icon('lock'){{ trans('entities.chapters_permissions_active') }}</a>
+                        <a href="{{ $chapter->getUrl('/permissions') }}" class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.chapters_permissions_active') }}</div>
+                        </a>
                     @else
-                        @icon('lock'){{ trans('entities.chapters_permissions_active') }}
+                        <div class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.chapters_permissions_active') }}</div>
+                        </div>
                     @endif
                 </div>
             @endif
index 28587d4e8c0f8e09a4d56b6b47152087006df0cf..8e4148b88716e9b6be23029b351447e749012161 100644 (file)
@@ -5,7 +5,7 @@
 
         <div class="popup-header primary-background">
             <div class="popup-title">{{ $title }}</div>
-            <button refs="popup@hide" type="button" class="popup-header-close">x</button>
+            <button refs="popup@hide" type="button" class="popup-header-close">@icon('close')</button>
         </div>
 
         <div class="px-m py-m">
diff --git a/resources/views/common/export-styles.blade.php b/resources/views/common/export-styles.blade.php
deleted file mode 100644 (file)
index 1dfa6bb..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<style>
-    @if (!app()->runningUnitTests())
-        {!! file_get_contents(public_path('/dist/export-styles.css')) !!}
-    @endif
-</style>
-
-@if ($format === 'pdf')
-    <style>
-
-        /* PDF size adjustments */
-        body {
-            font-size: 14px;
-            line-height: 1.2;
-        }
-
-        h1, h2, h3, h4, h5, h6 {
-            line-height: 1.2;
-        }
-
-        table {
-            max-width: 800px !important;
-            font-size: 0.8em;
-            width: 100% !important;
-        }
-
-        table td {
-            width: auto !important;
-        }
-
-        /* Patches for CSS variable colors */
-        a {
-            color: {{ setting('app-color') }};
-        }
-
-        blockquote {
-            border-left-color: {{ setting('app-color') }};
-        }
-
-        /* Patches for content layout */
-        .page-content .float {
-            float: none !important;
-        }
-
-        .page-content img.align-left, .page-content img.align-right  {
-            float: none !important;
-            clear: both;
-            display: block;
-        }
-
-        @if($engine === \BookStack\Entities\Tools\PdfGenerator::ENGINE_DOMPDF)
-        {{-- Fix for full width linked image sizes on DOMPDF --}}
-        .page-content a > img {
-            max-width: 700px;
-        }
-        {{-- Undoes the above for table images to prevent visually worse scenario, Awaiting next DOMPDF release for patch --}}
-        .page-content td a > img {
-            max-width: 100%;
-        }
-        @endif
-    </style>
-@endif
\ No newline at end of file
index b5ac520c18f37755388da0be91cd2a43cf01bc11..197b80c27ec10c20da9399bd195d0e190d8e69e8 100644 (file)
@@ -17,7 +17,7 @@
                     class="mobile-menu-toggle hide-over-l">@icon('more')</button>
         </div>
 
-        <div class="flex-container-row justify-center hide-under-l">
+        <div class="flex-container-column items-center justify-center hide-under-l">
             @if (hasAppAccess())
             <form action="{{ url('/search') }}" method="GET" class="search-box" role="search">
                 <button id="header-search-box-button" type="submit" aria-label="{{ trans('common.search') }}" tabindex="-1">@icon('search') </button>
             @endif
         </div>
 
-        <div class="text-right">
-            <nav refs="header-mobile-toggle@menu" class="header-links">
-                <div class="links text-center">
-                    @if (hasAppAccess())
-                        <a class="hide-over-l" href="{{ url('/search') }}">@icon('search'){{ trans('common.search') }}</a>
-                        @if(userCanOnAny('view', \BookStack\Entities\Models\Bookshelf::class) || userCan('bookshelf-view-all') || userCan('bookshelf-view-own'))
-                            <a href="{{ url('/shelves') }}">@icon('bookshelf'){{ trans('entities.shelves') }}</a>
-                        @endif
-                        <a href="{{ url('/books') }}">@icon('books'){{ trans('entities.books') }}</a>
-                        @if(signedInUser() && userCan('settings-manage'))
-                            <a href="{{ url('/settings') }}">@icon('settings'){{ trans('settings.settings') }}</a>
-                        @endif
-                        @if(signedInUser() && userCan('users-manage') && !userCan('settings-manage'))
-                            <a href="{{ url('/settings/users') }}">@icon('users'){{ trans('settings.users') }}</a>
-                        @endif
+        <nav refs="header-mobile-toggle@menu" class="header-links">
+            <div class="links text-center">
+                @if (hasAppAccess())
+                    <a class="hide-over-l" href="{{ url('/search') }}">@icon('search'){{ trans('common.search') }}</a>
+                    @if(userCanOnAny('view', \BookStack\Entities\Models\Bookshelf::class) || userCan('bookshelf-view-all') || userCan('bookshelf-view-own'))
+                        <a href="{{ url('/shelves') }}">@icon('bookshelf'){{ trans('entities.shelves') }}</a>
                     @endif
+                    <a href="{{ url('/books') }}">@icon('books'){{ trans('entities.books') }}</a>
+                    @if(signedInUser() && userCan('settings-manage'))
+                        <a href="{{ url('/settings') }}">@icon('settings'){{ trans('settings.settings') }}</a>
+                    @endif
+                    @if(signedInUser() && userCan('users-manage') && !userCan('settings-manage'))
+                        <a href="{{ url('/settings/users') }}">@icon('users'){{ trans('settings.users') }}</a>
+                    @endif
+                @endif
 
-                    @if(!signedInUser())
-                        @if(setting('registration-enabled') && config('auth.method') === 'standard')
-                            <a href="{{ url('/register') }}">@icon('new-user'){{ trans('auth.sign_up') }}</a>
-                        @endif
-                        <a href="{{ url('/login')  }}">@icon('login'){{ trans('auth.log_in') }}</a>
+                @if(!signedInUser())
+                    @if(setting('registration-enabled') && config('auth.method') === 'standard')
+                        <a href="{{ url('/register') }}">@icon('new-user'){{ trans('auth.sign_up') }}</a>
                     @endif
-                </div>
-                @if(signedInUser())
-                    <?php $currentUser = user(); ?>
-                    <div class="dropdown-container" component="dropdown" option:dropdown:bubble-escapes="true">
+                    <a href="{{ url('/login')  }}">@icon('login'){{ trans('auth.log_in') }}</a>
+                @endif
+            </div>
+            @if(signedInUser())
+                <?php $currentUser = user(); ?>
+                <div class="dropdown-container" component="dropdown" option:dropdown:bubble-escapes="true">
                         <span class="user-name py-s hide-under-l" refs="dropdown@toggle"
                               aria-haspopup="true" aria-expanded="false" aria-label="{{ trans('common.profile_menu') }}" tabindex="0">
                             <img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}">
                             <span class="name">{{ $currentUser->getShortName(9) }}</span> @icon('caret-down')
                         </span>
-                        <ul refs="dropdown@menu" class="dropdown-menu" role="menu">
-                            <li>
-                                <a href="{{ url('/favourites') }}" class="icon-item">
-                                    @icon('star')
-                                    <div>{{ trans('entities.my_favourites') }}</div>
-                                </a>
-                            </li>
-                            <li>
-                                <a href="{{ $currentUser->getProfileUrl() }}" class="icon-item">
-                                    @icon('user')
-                                    <div>{{ trans('common.view_profile') }}</div>
-                                </a>
-                            </li>
-                            <li>
-                                <a href="{{ $currentUser->getEditUrl() }}" class="icon-item">
-                                    @icon('edit')
-                                    <div>{{ trans('common.edit_profile') }}</div>
-                                </a>
-                            </li>
-                            <li>
-                                <form action="{{ url(config('auth.method') === 'saml2' ? '/saml2/logout' : '/logout') }}"
-                                      method="post">
-                                    {{ csrf_field() }}
-                                    <button class="icon-item">
-                                        @icon('logout')
-                                        <div>{{ trans('auth.logout') }}</div>
-                                    </button>
-                                </form>
-                            </li>
-                            <li><hr></li>
-                            <li>
-                                @include('common.dark-mode-toggle', ['classes' => 'icon-item'])
-                            </li>
-                        </ul>
-                    </div>
-                @endif
-            </nav>
-        </div>
+                    <ul refs="dropdown@menu" class="dropdown-menu" role="menu">
+                        <li>
+                            <a href="{{ url('/favourites') }}" class="icon-item">
+                                @icon('star')
+                                <div>{{ trans('entities.my_favourites') }}</div>
+                            </a>
+                        </li>
+                        <li>
+                            <a href="{{ $currentUser->getProfileUrl() }}" class="icon-item">
+                                @icon('user')
+                                <div>{{ trans('common.view_profile') }}</div>
+                            </a>
+                        </li>
+                        <li>
+                            <a href="{{ $currentUser->getEditUrl() }}" class="icon-item">
+                                @icon('edit')
+                                <div>{{ trans('common.edit_profile') }}</div>
+                            </a>
+                        </li>
+                        <li>
+                            <form action="{{ url(config('auth.method') === 'saml2' ? '/saml2/logout' : '/logout') }}"
+                                  method="post">
+                                {{ csrf_field() }}
+                                <button class="icon-item">
+                                    @icon('logout')
+                                    <div>{{ trans('auth.logout') }}</div>
+                                </button>
+                            </form>
+                        </li>
+                        <li><hr></li>
+                        <li>
+                            @include('common.dark-mode-toggle', ['classes' => 'icon-item'])
+                        </li>
+                    </ul>
+                </div>
+            @endif
+        </nav>
 
     </div>
 </header>
index 929f56ed3c62e53b29e6ffde41d84186be90ac0e..1efe3ba34ca97253220f2502facc222fb513bfc5 100644 (file)
@@ -2,7 +2,7 @@
      option:dropdown-search:url="/search/entity/siblings?entity_type={{$entity->getType()}}&entity_id={{ $entity->id }}"
      option:dropdown-search:local-search-selector=".entity-list-item"
 >
-    <div class="dropdown-search-toggle" refs="dropdown@toggle"
+    <div class="dropdown-search-toggle-breadcrumb" refs="dropdown@toggle"
          aria-haspopup="true" aria-expanded="false" tabindex="0">
         <div class="separator">@icon('chevron-right')</div>
     </div>
@@ -18,6 +18,6 @@
         <div refs="dropdown-search@loading">
             @include('common.loading-icon')
         </div>
-        <div refs="dropdown-search@listContainer" class="dropdown-search-list px-m"></div>
+        <div refs="dropdown-search@listContainer" class="dropdown-search-list px-m" tabindex="-1"></div>
     </div>
 </div>
\ No newline at end of file
index dd7231095b8f6ebf3e7e14ec9d9674adfbceb999..bac240b1eed0c2a493b3ba8b09727067c08bf4c6 100644 (file)
@@ -1,13 +1,18 @@
-<div component="dropdown" class="dropdown-container" id="export-menu">
+<div component="dropdown"
+     class="dropdown-container"
+     id="export-menu">
+
     <div refs="dropdown@toggle" class="icon-list-item"
          aria-haspopup="true" aria-expanded="false" aria-label="{{ trans('entities.export') }}" tabindex="0">
         <span>@icon('export')</span>
         <span>{{ trans('entities.export') }}</span>
     </div>
+
     <ul refs="dropdown@menu" class="wide dropdown-menu" role="menu">
         <li><a href="{{ $entity->getUrl('/export/html') }}" target="_blank" class="label-item"><span>{{ trans('entities.export_html') }}</span><span>.html</span></a></li>
         <li><a href="{{ $entity->getUrl('/export/pdf') }}" target="_blank" class="label-item"><span>{{ trans('entities.export_pdf') }}</span><span>.pdf</span></a></li>
         <li><a href="{{ $entity->getUrl('/export/plaintext') }}" target="_blank" class="label-item"><span>{{ trans('entities.export_text') }}</span><span>.txt</span></a></li>
         <li><a href="{{ $entity->getUrl('/export/markdown') }}" target="_blank" class="label-item"><span>{{ trans('entities.export_md') }}</span><span>.md</span></a></li>
     </ul>
+
 </div>
index 298cc7c3e421750c6ec9669b2fcd9fb0a229f319..83ff2376220afe9dce33ff85904bc1ba5a515320 100644 (file)
@@ -1,50 +1,62 @@
 <div class="entity-meta">
     @if($entity->isA('revision'))
-        <div>
-            @icon('history'){{ trans('entities.pages_revision') }}
-            {{ trans('entities.pages_revisions_number') }}{{ $entity->revision_number == 0 ? '' : $entity->revision_number }}
+        <div class="entity-meta-item">
+            @icon('history')
+            <div>
+                {{ trans('entities.pages_revision') }}
+                {{ trans('entities.pages_revisions_number') }}{{ $entity->revision_number == 0 ? '' : $entity->revision_number }}
+            </div>
         </div>
     @endif
 
     @if ($entity->isA('page'))
-        <div>
-            @if (userCan('page-update', $entity)) <a href="{{ $entity->getUrl('/revisions') }}"> @endif
-            @icon('history'){{ trans('entities.meta_revision', ['revisionCount' => $entity->revision_count]) }}
-            @if (userCan('page-update', $entity))</a>@endif
-        </div>
+        @if (userCan('page-update', $entity)) <a href="{{ $entity->getUrl('/revisions') }}" class="entity-meta-item"> @else <div class="entity-meta-item"> @endif
+        @icon('history'){{ trans('entities.meta_revision', ['revisionCount' => $entity->revision_count]) }}
+        @if (userCan('page-update', $entity))</a> @else </div> @endif
     @endif
 
     @if ($entity->ownedBy && $entity->owned_by !== $entity->created_by)
-        <div>
-            @icon('user'){!! trans('entities.meta_owned_name', [
-            'user' => "<a href='{$entity->ownedBy->getProfileUrl()}'>".e($entity->ownedBy->name). "</a>"
-        ]) !!}
+        <div class="entity-meta-item">
+            @icon('user')
+            <div>
+                {!! trans('entities.meta_owned_name', [
+                    'user' => "<a href='{$entity->ownedBy->getProfileUrl()}'>".e($entity->ownedBy->name). "</a>"
+                ]) !!}
+            </div>
         </div>
     @endif
 
     @if ($entity->createdBy)
-        <div>
-            @icon('star'){!! trans('entities.meta_created_name', [
-            'timeLength' => '<span title="'.$entity->created_at->toDayDateTimeString().'">'.$entity->created_at->diffForHumans() . '</span>',
-            'user' => "<a href='{$entity->createdBy->getProfileUrl()}'>".e($entity->createdBy->name). "</a>"
-            ]) !!}
+        <div class="entity-meta-item">
+            @icon('star')
+            <div>
+                {!! trans('entities.meta_created_name', [
+                    'timeLength' => '<span title="'.$entity->created_at->toDayDateTimeString().'">'.$entity->created_at->diffForHumans() . '</span>',
+                    'user' => "<a href='{$entity->createdBy->getProfileUrl()}'>".e($entity->createdBy->name). "</a>"
+                ]) !!}
+            </div>
         </div>
     @else
-        <div>
-            @icon('star')<span title="{{$entity->created_at->toDayDateTimeString()}}">{{ trans('entities.meta_created', ['timeLength' => $entity->created_at->diffForHumans()]) }}</span>
+        <div class="entity-meta-item">
+            @icon('star')
+            <span title="{{$entity->created_at->toDayDateTimeString()}}">{{ trans('entities.meta_created', ['timeLength' => $entity->created_at->diffForHumans()]) }}</span>
         </div>
     @endif
 
     @if ($entity->updatedBy)
-        <div>
-            @icon('edit'){!! trans('entities.meta_updated_name', [
-                'timeLength' => '<span title="' . $entity->updated_at->toDayDateTimeString() .'">' . $entity->updated_at->diffForHumans() .'</span>',
-                'user' => "<a href='{$entity->updatedBy->getProfileUrl()}'>".e($entity->updatedBy->name). "</a>"
-            ]) !!}
+        <div class="entity-meta-item">
+            @icon('edit')
+            <div>
+                {!! trans('entities.meta_updated_name', [
+                    'timeLength' => '<span title="' . $entity->updated_at->toDayDateTimeString() .'">' . $entity->updated_at->diffForHumans() .'</span>',
+                    'user' => "<a href='{$entity->updatedBy->getProfileUrl()}'>".e($entity->updatedBy->name). "</a>"
+                ]) !!}
+            </div>
         </div>
     @elseif (!$entity->isA('revision'))
-        <div>
-            @icon('edit')<span title="{{ $entity->updated_at->toDayDateTimeString() }}">{{ trans('entities.meta_updated', ['timeLength' => $entity->updated_at->diffForHumans()]) }}</span>
+        <div class="entity-meta-item">
+            @icon('edit')
+            <span title="{{ $entity->updated_at->toDayDateTimeString() }}">{{ trans('entities.meta_updated', ['timeLength' => $entity->updated_at->diffForHumans()]) }}</span>
         </div>
     @endif
 </div>
\ No newline at end of file
index ab73a014fa8d2a6c52b68c3c0ec97823414164e0..c896b50b5234ab25bddcca53ecc7408112ef8aa4 100644 (file)
@@ -3,11 +3,11 @@
         <div class="popup-body small" tabindex="-1">
             <div class="popup-header primary-background">
                 <div class="popup-title">{{ trans('entities.entity_select') }}</div>
-                <button refs="popup@hide" type="button" class="popup-header-close">x</button>
+                <button refs="popup@hide" type="button" class="popup-header-close">@icon('close')</button>
             </div>
             @include('entities.selector', ['name' => 'entity-selector'])
             <div class="popup-footer">
-                <button refs="entity-selector-popup@select" type="button" disabled="true" class="button corner-button">{{ trans('common.select') }}</button>
+                <button refs="entity-selector-popup@select" type="button" disabled="true" class="button">{{ trans('common.select') }}</button>
             </div>
         </div>
     </div>
diff --git a/resources/views/exports/book.blade.php b/resources/views/exports/book.blade.php
new file mode 100644 (file)
index 0000000..42e03ea
--- /dev/null
@@ -0,0 +1,20 @@
+@extends('layouts.export')
+
+@section('title', $book->name)
+
+@section('content')
+
+    <h1 style="font-size: 4.8em">{{$book->name}}</h1>
+    <p>{{ $book->description }}</p>
+
+    @include('exports.parts.book-contents-menu', ['children' => $bookChildren])
+
+    @foreach($bookChildren as $bookChild)
+        @if($bookChild->isA('chapter'))
+            @include('exports.parts.chapter-item', ['chapter' => $bookChild])
+        @else
+            @include('exports.parts.page-item', ['page' => $bookChild, 'chapter' => null])
+        @endif
+    @endforeach
+
+@endsection
\ No newline at end of file
diff --git a/resources/views/exports/chapter.blade.php b/resources/views/exports/chapter.blade.php
new file mode 100644 (file)
index 0000000..ae49fa9
--- /dev/null
@@ -0,0 +1,16 @@
+@extends('layouts.export')
+
+@section('title', $chapter->name)
+
+@section('content')
+
+    <h1 style="font-size: 4.8em">{{$chapter->name}}</h1>
+    <p>{{ $chapter->description }}</p>
+
+    @include('exports.parts.chapter-contents-menu', ['pages' => $pages])
+
+    @foreach($pages as $page)
+        @include('exports.parts.page-item', ['page' => $page, 'chapter' => null])
+    @endforeach
+
+@endsection
\ No newline at end of file
similarity index 71%
rename from resources/views/pages/export.blade.php
rename to resources/views/exports/page.blade.php
index d2f448d6e889bd430f3ce53852530d8411c2945c..e9324e96b9924c7d11f261e17e52387563abe630 100644 (file)
@@ -8,6 +8,6 @@
     <hr>
 
     <div class="text-muted text-small">
-        @include('entities.export-meta', ['entity' => $page])
+        @include('exports.parts.meta', ['entity' => $page])
     </div>
 @endsection
\ No newline at end of file
diff --git a/resources/views/exports/parts/book-contents-menu.blade.php b/resources/views/exports/parts/book-contents-menu.blade.php
new file mode 100644 (file)
index 0000000..6b75442
--- /dev/null
@@ -0,0 +1,10 @@
+@if(count($children) > 0)
+    <ul class="contents">
+        @foreach($children as $bookChild)
+            <li><a href="#{{$bookChild->getType()}}-{{$bookChild->id}}">{{ $bookChild->name }}</a></li>
+            @if($bookChild->isA('chapter') && count($bookChild->visible_pages) > 0)
+                @include('exports.parts.chapter-contents-menu', ['pages' => $bookChild->visible_pages])
+            @endif
+        @endforeach
+    </ul>
+@endif
\ No newline at end of file
diff --git a/resources/views/exports/parts/chapter-contents-menu.blade.php b/resources/views/exports/parts/chapter-contents-menu.blade.php
new file mode 100644 (file)
index 0000000..eeaa349
--- /dev/null
@@ -0,0 +1,7 @@
+@if (count($pages) > 0)
+        <ul class="contents">
+            @foreach($pages as $page)
+                <li><a href="#page-{{$page->id}}">{{ $page->name }}</a></li>
+            @endforeach
+        </ul>
+@endif
\ No newline at end of file
diff --git a/resources/views/exports/parts/chapter-item.blade.php b/resources/views/exports/parts/chapter-item.blade.php
new file mode 100644 (file)
index 0000000..f58068b
--- /dev/null
@@ -0,0 +1,10 @@
+<div class="page-break"></div>
+<h1 id="chapter-{{$chapter->id}}">{{ $chapter->name }}</h1>
+
+<p>{{ $chapter->description }}</p>
+
+@if(count($chapter->visible_pages) > 0)
+    @foreach($chapter->visible_pages as $page)
+        @include('exports.parts.page-item', ['page' => $page, 'chapter' => $chapter])
+    @endforeach
+@endif
\ No newline at end of file
diff --git a/resources/views/exports/parts/page-item.blade.php b/resources/views/exports/parts/page-item.blade.php
new file mode 100644 (file)
index 0000000..1a138ae
--- /dev/null
@@ -0,0 +1,8 @@
+<div class="page-break"></div>
+
+@if (isset($chapter))
+    <div class="chapter-hint">{{$chapter->name}}</div>
+@endif
+
+<h1 id="page-{{$page->id}}">{{ $page->name }}</h1>
+{!! $page->html !!}
\ No newline at end of file
diff --git a/resources/views/exports/parts/styles.blade.php b/resources/views/exports/parts/styles.blade.php
new file mode 100644 (file)
index 0000000..830b8e4
--- /dev/null
@@ -0,0 +1,20 @@
+{{-- Fetch in our standard export styles --}}
+<style>
+    @if (!app()->runningUnitTests())
+        {!! file_get_contents(public_path('/dist/export-styles.css')) !!}
+    @endif
+</style>
+
+{{-- Apply any additional styles that can't be applied via our standard SCSS export styles --}}
+@if ($format === 'pdf')
+    <style>
+        /* Patches for CSS variable colors within PDF exports */
+        a {
+            color: {{ setting('app-color') }};
+        }
+
+        blockquote {
+            border-left-color: {{ setting('app-color') }};
+        }
+    </style>
+@endif
\ No newline at end of file
index ed04bc04124c9c0302568b8b4135390ce1314289..206955fe94864021f23bac4b07082a6f0a09e362 100644 (file)
@@ -15,7 +15,7 @@
         <div>
             <div class="form-group">
                 <label for="owner">{{ trans('entities.permissions_owner') }}</label>
-                @include('form.user-select', ['user' => $model->ownedBy, 'name' => 'owned_by', 'compact' => false])
+                @include('form.user-select', ['user' => $model->ownedBy, 'name' => 'owned_by'])
             </div>
         </div>
     </div>
index 8823bb0750b5fdb014cae14bf0dcf1ca630ce46f..743795a6daa3b4451bd268d40abfe75d5ada5a12 100644 (file)
@@ -1,19 +1,19 @@
-<div class="dropdown-search custom-select-input" components="dropdown dropdown-search user-select"
+<div class="dropdown-search" components="dropdown dropdown-search user-select"
      option:dropdown-search:url="/search/users/select"
 >
     <input refs="user-select@input" type="hidden" name="{{ $name }}" value="{{ $user->id ?? '' }}">
     <div refs="dropdown@toggle"
-         class="dropdown-search-toggle {{ $compact ? 'compact' : '' }} flex-container-row items-center"
+         class="dropdown-search-toggle-select  input-base"
          aria-haspopup="true" aria-expanded="false" tabindex="0">
-        <div refs="user-select@user-info" class="flex-container-row items-center px-s">
+        <div refs="user-select@user-info" class="dropdown-search-toggle-select-label flex-container-row items-center">
             @if($user)
-                <img class="avatar small mr-m" src="{{ $user->getAvatar($compact ? 22 : 30) }}" alt="{{ $user->name }}">
+                <img class="avatar small mr-m" src="{{ $user->getAvatar(30) }}" width="30" height="30" alt="{{ $user->name }}">
                 <span>{{ $user->name }}</span>
             @else
                 <span>{{ trans('settings.users_none_selected') }}</span>
             @endif
         </div>
-        <span style="font-size: {{ $compact ? '1.15rem' : '1.5rem' }}; margin-left: auto;">
+        <span class="dropdown-search-toggle-select-caret">
             @icon('caret-down')
         </span>
     </div>
index 6435e4ebdc0f760801fa8c9dd6ded8bedf58f681..f6a337e5054d4bd7b978fc08c626253270d278ed 100644 (file)
         </div>
     </div>
 
-    <script nonce="{{ $cspNonce }}">
-        setTimeout(async () => {
-            const result = await window.components["confirm-dialog"][0].show();
-            console.log({result});
-        }, 1000);
-    </script>
-
     <div class="container" id="home-default">
         <div class="grid third gap-xxl no-row-gap" >
             <div>
index 1f28e354ce8e119f03a0281fde89563eaee371d5..c465c5f7ef59d2ade5dbcf852e7f8f14269dac86 100644 (file)
@@ -33,6 +33,7 @@
 </head>
 <body class="@yield('body-class')">
 
+    @include('layouts.parts.base-body-start')
     @include('common.skip-to-content')
     @include('common.notifications')
     @include('common.header')
@@ -53,5 +54,6 @@
     <script src="{{ versioned_asset('dist/app.js') }}" nonce="{{ $cspNonce }}"></script>
     @yield('scripts')
 
+    @include('layouts.parts.base-body-end')
 </body>
 </html>
index 36568fef4dad22efa7876f9825ebd90336b9d6bb..d631ad3c9bf81db2a70badcf0acf11260a6eddc3 100644 (file)
@@ -8,10 +8,10 @@
         <meta http-equiv="Content-Security-Policy" content="{{ $cspContent }}">
     @endif
 
-    @include('common.export-styles', ['format' => $format, 'engine' => $engine ?? ''])
-    @include('common.export-custom-head')
+    @include('exports.parts.styles', ['format' => $format, 'engine' => $engine ?? ''])
+    @include('exports.parts.custom-head')
 </head>
-<body>
+<body class="export export-format-{{ $format }} export-engine-{{ $engine ?? 'none' }}">
 <div class="page-content">
     @yield('content')
 </div>
diff --git a/resources/views/layouts/parts/base-body-end.blade.php b/resources/views/layouts/parts/base-body-end.blade.php
new file mode 100644 (file)
index 0000000..4711989
--- /dev/null
@@ -0,0 +1,2 @@
+{{-- This is a placeholder template file provided as a --}}
+{{-- convenience to users of the visual theme system. --}}
\ No newline at end of file
diff --git a/resources/views/layouts/parts/base-body-start.blade.php b/resources/views/layouts/parts/base-body-start.blade.php
new file mode 100644 (file)
index 0000000..4711989
--- /dev/null
@@ -0,0 +1,2 @@
+{{-- This is a placeholder template file provided as a --}}
+{{-- convenience to users of the visual theme system. --}}
\ No newline at end of file
index e95b21445295e851368ead241ef92d08353a6cdc..4571f4471ca94cd59428e9a73d4e20122c120129 100644 (file)
@@ -27,7 +27,7 @@
 
     <div refs="tri-layout@container" class="tri-layout-container" @yield('container-attrs') >
 
-        <div class="tri-layout-left print-hidden pt-m" id="sidebar">
+        <div class="tri-layout-left print-hidden" id="sidebar">
             <aside class="tri-layout-left-contents">
                 @yield('left')
             </aside>
@@ -39,7 +39,7 @@
             </div>
         </div>
 
-        <div class="tri-layout-right print-hidden pt-m">
+        <div class="tri-layout-right print-hidden">
             <aside class="tri-layout-right-contents">
                 @yield('right')
             </aside>
index c593d0e2389adde14d7091a3f3d7b73c19a1ae10..4ac688692ef81619dc6c6b6962fc24b217d2bdf4 100644 (file)
@@ -2,68 +2,69 @@
     <div components="popup code-editor" class="popup-background code-editor">
         <div refs="code-editor@container" class="popup-body" tabindex="-1">
 
-            <div class="popup-header primary-background">
+            <div class="popup-header flex-container-row primary-background">
                 <div class="popup-title">{{ trans('components.code_editor') }}</div>
-                <button class="popup-header-close" refs="popup@hide">x</button>
+                <div component="dropdown" refs="code-editor@historyDropDown" class="flex-container-row">
+                    <button refs="dropdown@toggle">
+                        <span>@icon('history')</span>
+                        <span>{{ trans('components.code_session_history') }}</span>
+                    </button>
+                    <ul refs="dropdown@menu code-editor@historyList" class="dropdown-menu"></ul>
+                </div>
+                <button class="popup-header-close" refs="popup@hide">@icon('close')</button>
             </div>
 
-            <div class="p-l popup-content">
-                <div class="form-group">
+            <div class="code-editor-body-wrap flex-container-row flex-fill">
+                <div class="code-editor-language-list flex-container-column flex-fill">
                     <label for="code-editor-language">{{ trans('components.code_language') }}</label>
+                    <input refs="code-editor@languageInput" id="code-editor-language" type="text">
                     <div class="lang-options">
-                        <small>
-                            <a refs="code-editor@languageLink" data-lang="CSS">CSS</a>
-                            <a refs="code-editor@languageLink" data-lang="C">C</a>
-                            <a refs="code-editor@languageLink" data-lang="C++">C++</a>
-                            <a refs="code-editor@languageLink" data-lang="C#">C#</a>
-                            <a refs="code-editor@languageLink" data-lang="Fortran">Fortran</a>
-                            <a refs="code-editor@languageLink" data-lang="Go">Go</a>
-                            <a refs="code-editor@languageLink" data-lang="HTML">HTML</a>
-                            <a refs="code-editor@languageLink" data-lang="INI">INI</a>
-                            <a refs="code-editor@languageLink" data-lang="Java">Java</a>
-                            <a refs="code-editor@languageLink" data-lang="JavaScript">JavaScript</a>
-                            <a refs="code-editor@languageLink" data-lang="JSON">JSON</a>
-                            <a refs="code-editor@languageLink" data-lang="Lua">Lua</a>
-                            <a refs="code-editor@languageLink" data-lang="MarkDown">MarkDown</a>
-                            <a refs="code-editor@languageLink" data-lang="Nginx">Nginx</a>
-                            <a refs="code-editor@languageLink" data-lang="PASCAL">Pascal</a>
-                            <a refs="code-editor@languageLink" data-lang="Perl">Perl</a>
-                            <a refs="code-editor@languageLink" data-lang="PHP">PHP</a>
-                            <a refs="code-editor@languageLink" data-lang="Powershell">Powershell</a>
-                            <a refs="code-editor@languageLink" data-lang="Python">Python</a>
-                            <a refs="code-editor@languageLink" data-lang="Ruby">Ruby</a>
-                            <a refs="code-editor@languageLink" data-lang="shell">Shell/Bash</a>
-                            <a refs="code-editor@languageLink" data-lang="SQL">SQL</a>
-                            <a refs="code-editor@languageLink" data-lang="VBScript">VBScript</a>
-                            <a refs="code-editor@languageLink" data-lang="VB.NET">VB.NET</a>
-                            <a refs="code-editor@languageLink" data-lang="XML">XML</a>
-                            <a refs="code-editor@languageLink" data-lang="YAML">YAML</a>
-                        </small>
+                        <button type="button" refs="code-editor@languageLink" data-lang="CSS">CSS</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="C">C</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="C++">C++</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="C#">C#</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="diff">Diff</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Fortran">Fortran</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="F#">F#</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Go">Go</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Haskell">Haskell</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="HTML">HTML</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="INI">INI</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Java">Java</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="JavaScript">JavaScript</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="JSON">JSON</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Julia">Julia</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="kotlin">Kotlin</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="LaTeX">LaTeX</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Lua">Lua</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="MarkDown">MarkDown</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Nginx">Nginx</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="ocaml">OCaml</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="PASCAL">Pascal</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Perl">Perl</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="PHP">PHP</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Powershell">Powershell</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Python">Python</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="Ruby">Ruby</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="rust">Rust</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="shell">Shell/Bash</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="SQL">SQL</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="typescript">TypeScript</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="VBScript">VBScript</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="VB.NET">VB.NET</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="XML">XML</button>
+                        <button type="button" refs="code-editor@languageLink" data-lang="YAML">YAML</button>
                     </div>
-                    <input refs="code-editor@languageInput" id="code-editor-language" type="text">
                 </div>
 
-                <div class="form-group">
-                    <div class="grid half no-break v-end mb-xs">
-                        <div>
-                            <label for="code-editor-content">{{ trans('components.code_content') }}</label>
-                        </div>
-                        <div class="text-right">
-                            <div component="dropdown" refs="code-editor@historyDropDown" class="inline block">
-                                <button refs="dropdown@toggle" class="text-button text-small">@icon('history') {{ trans('components.code_session_history') }}</button>
-                                <ul refs="dropdown@menu code-editor@historyList" class="dropdown-menu"></ul>
-                            </div>
-                        </div>
-                    </div>
-
-                    <div class="clearfix"></div>
+                <div class="code-editor-main flex-fill">
                     <textarea refs="code-editor@editor"></textarea>
                 </div>
 
-                <div class="form-group">
-                    <button refs="code-editor@saveButton" type="button" class="button">{{ trans('components.code_save') }}</button>
-                </div>
+            </div>
 
+            <div class="popup-footer">
+                <button refs="code-editor@saveButton" type="button" class="button">{{ trans('components.code_save') }}</button>
             </div>
 
         </div>
index 4846f4b761299adf6822ae5d8097ff7d4ca469d9..fa5cb7374eb31586db5d89a2e115f35f1400166b 100644 (file)
@@ -65,7 +65,9 @@
         </div>
 
         <div class="action-buttons px-m py-xs">
-            <div component="dropdown" dropdown-move-menu class="dropdown-container">
+            <div component="dropdown"
+                 option:dropdown:move-menu="true"
+                 class="dropdown-container">
                 <button refs="dropdown@toggle" type="button" aria-haspopup="true" aria-expanded="false" class="text-primary text-button">@icon('edit') <span refs="page-editor@changelogDisplay">{{ trans('entities.pages_edit_set_changelog') }}</span></button>
                 <ul refs="dropdown@menu" class="wide dropdown-menu">
                     <li class="px-l py-m">
index c15c31b86904bc1c7985cb20ac90663c6f053670..50a0cd8c370e5be57a51f90f051423d065e9e9b3 100644 (file)
@@ -9,7 +9,7 @@
 
             <div class="popup-header primary-background">
                 <div class="popup-title">{{ trans('components.image_select') }}</div>
-                <button refs="popup@hide" type="button" class="popup-header-close">x</button>
+                <button refs="popup@hide" type="button" class="popup-header-close">@icon('close')</button>
             </div>
 
             <div class="flex-fill image-manager-body">
                     </div>
 
                     <div refs="image-manager@formContainer" class="inner flex"></div>
-
-                    <button refs="image-manager@selectButton" type="button" class="hidden button corner-button">
-                        {{ trans('components.image_select_image') }}
-                    </button>
                 </div>
 
             </div>
 
+            <div class="popup-footer">
+                <button refs="image-manager@selectButton" type="button" class="hidden button">
+                    {{ trans('components.image_select_image') }}
+                </button>
+            </div>
+
         </div>
     </div>
 </div>
\ No newline at end of file
index 0111047c6cfec38fe0a2fea304226c7de3a6f114..2a71c60214183698826027c2ecc0797cc1444e34 100644 (file)
 @section('right')
     <div id="page-details" class="entity-details mb-xl">
         <h5>{{ trans('common.details') }}</h5>
-        <div class="body text-small blended-links">
+        <div class="blended-links">
             @include('entities.meta', ['entity' => $page])
 
             @if($book->restricted)
                 <div class="active-restriction">
                     @if(userCan('restrictions-manage', $book))
-                        <a href="{{ $book->getUrl('/permissions') }}">@icon('lock'){{ trans('entities.books_permissions_active') }}</a>
+                        <a href="{{ $book->getUrl('/permissions') }}" class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.books_permissions_active') }}</div>
+                        </a>
                     @else
-                        @icon('lock'){{ trans('entities.books_permissions_active') }}
+                        <div class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.books_permissions_active') }}</div>
+                        </div>
                     @endif
                 </div>
             @endif
             @if($page->chapter && $page->chapter->restricted)
                 <div class="active-restriction">
                     @if(userCan('restrictions-manage', $page->chapter))
-                        <a href="{{ $page->chapter->getUrl('/permissions') }}">@icon('lock'){{ trans('entities.chapters_permissions_active') }}</a>
+                        <a href="{{ $page->chapter->getUrl('/permissions') }}" class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.chapters_permissions_active') }}</div>
+                        </a>
                     @else
-                        @icon('lock'){{ trans('entities.chapters_permissions_active') }}
+                        <div class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.chapters_permissions_active') }}</div>
+                        </div>
                     @endif
                 </div>
             @endif
             @if($page->restricted)
                 <div class="active-restriction">
                     @if(userCan('restrictions-manage', $page))
-                        <a href="{{ $page->getUrl('/permissions') }}">@icon('lock'){{ trans('entities.pages_permissions_active') }}</a>
+                        <a href="{{ $page->getUrl('/permissions') }}" class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.pages_permissions_active') }}</div>
+                        </a>
                     @else
-                        @icon('lock'){{ trans('entities.pages_permissions_active') }}
+                        <div class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.pages_permissions_active') }}</div>
+                        </div>
                     @endif
                 </div>
             @endif
 
             @if($page->template)
-                <div>
-                    @icon('template'){{ trans('entities.pages_is_template') }}
+                <div class="entity-meta-item">
+                    @icon('template')
+                    <div>{{ trans('entities.pages_is_template') }}</div>
                 </div>
             @endif
         </div>
index 506a735a2c59552825334a2d4729bbc73831fb4d..b856d11502a5dd05fe7bf1879012afc04528c53a 100644 (file)
@@ -9,8 +9,9 @@
         <h1 class="list-heading">{{ trans('settings.audit') }}</h1>
         <p class="text-muted">{{ trans('settings.audit_desc') }}</p>
 
-        <div class="flex-container-row">
-            <div component="dropdown" class="list-sort-type dropdown-container mr-m">
+        <form action="{{ url('/settings/audit') }}" method="get" class="flex-container-row wrap justify-flex-start gap-m">
+
+            <div component="dropdown" class="list-sort-type dropdown-container">
                 <label for="">{{ trans('settings.audit_event_filter') }}</label>
                 <button refs="dropdown@toggle" aria-haspopup="true" aria-expanded="false" aria-label="{{ trans('common.sort_options') }}" class="input-base text-left">{{ $listDetails['event'] ?: trans('settings.audit_event_filter_no_filter') }}</button>
                 <ul refs="dropdown@menu" class="dropdown-menu">
                 </ul>
             </div>
 
-            <form action="{{ url('/settings/audit') }}" method="get" class="flex-container-row mr-m">
-                @if(!empty($listDetails['event']))
-                    <input type="hidden" name="event" value="{{ $listDetails['event'] }}">
-                @endif
-
-                @foreach(['date_from', 'date_to'] as $filterKey)
-                    <div class="mr-m">
-                        <label for="audit_filter_{{ $filterKey }}">{{ trans('settings.audit_' . $filterKey) }}</label>
-                        <input id="audit_filter_{{ $filterKey }}"
-                               component="submit-on-change"
-                               type="date"
-                               name="{{ $filterKey }}"
-                               value="{{ $listDetails[$filterKey] ?? '' }}">
-                    </div>
-                @endforeach
+            @if(!empty($listDetails['event']))
+                <input type="hidden" name="event" value="{{ $listDetails['event'] }}">
+            @endif
 
-                <div class="form-group ml-auto mr-m"
-                     component="submit-on-change"
-                     option:submit-on-change:filter='[name="user"]'>
-                    <label for="owner">{{ trans('settings.audit_table_user') }}</label>
-                    @include('form.user-select', ['user' => $listDetails['user'] ? \BookStack\Auth\User::query()->find($listDetails['user']) : null, 'name' => 'user', 'compact' =>  true])
+            @foreach(['date_from', 'date_to'] as $filterKey)
+                <div class=>
+                    <label for="audit_filter_{{ $filterKey }}">{{ trans('settings.audit_' . $filterKey) }}</label>
+                    <input id="audit_filter_{{ $filterKey }}"
+                           component="submit-on-change"
+                           type="date"
+                           name="{{ $filterKey }}"
+                           value="{{ $listDetails[$filterKey] ?? '' }}">
                 </div>
+            @endforeach
 
+            <div class="form-group"
+                 component="submit-on-change"
+                 option:submit-on-change:filter='[name="user"]'>
+                <label for="owner">{{ trans('settings.audit_table_user') }}</label>
+                @include('form.user-select', ['user' => $listDetails['user'] ? \BookStack\Auth\User::query()->find($listDetails['user']) : null, 'name' => 'user'])
+            </div>
 
-                <div class="form-group ml-auto">
-                    <label for="ip">{{ trans('settings.audit_table_ip') }}</label>
-                    @include('form.text', ['name' => 'ip', 'model' => (object) $listDetails])
-                    <input type="submit" style="display: none">
-                </div>
-            </form>
-        </div>
+
+            <div class="form-group">
+                <label for="ip">{{ trans('settings.audit_table_ip') }}</label>
+                @include('form.text', ['name' => 'ip', 'model' => (object) $listDetails])
+                <input type="submit" style="display: none">
+            </div>
+        </form>
 
         <hr class="mt-l mb-s">
 
index b7be95b4a1519ac53da4b746c942300627b308a3..a7392196b68be6ad0329a57dffbb9c0191ea4052 100644 (file)
             <div>
                 <label for="setting-app-custom-head" class="setting-list-label">{{ trans('settings.app_custom_html') }}</label>
                 <p class="small">{{ trans('settings.app_custom_html_desc') }}</p>
-                <textarea name="setting-app-custom-head" id="setting-app-custom-head" class="simple-code-input mt-m">{{ setting('app-custom-head', '') }}</textarea>
+                <div class="mt-m">
+                    <textarea component="code-textarea"
+                              option:code-textarea:mode="html"
+                              name="setting-app-custom-head"
+                              id="setting-app-custom-head"
+                              class="simple-code-input">{{ setting('app-custom-head', '') }}</textarea>
+                </div>
                 <p class="small text-right">{{ trans('settings.app_custom_html_disabled_notice') }}</p>
             </div>
 
index 0d592468d1b8a1adace0bc1776695a779a4bd13a..4d440b635f4f83e386f47fdb4cfb07d5ad0a9372 100644 (file)
 
     <div id="details" class="mb-xl">
         <h5>{{ trans('common.details') }}</h5>
-        <div class="text-small text-muted blended-links">
+        <div class="blended-links">
             @include('entities.meta', ['entity' => $shelf])
             @if($shelf->restricted)
                 <div class="active-restriction">
                     @if(userCan('restrictions-manage', $shelf))
-                        <a href="{{ $shelf->getUrl('/permissions') }}">@icon('lock'){{ trans('entities.shelves_permissions_active') }}</a>
+                        <a href="{{ $shelf->getUrl('/permissions') }}" class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.shelves_permissions_active') }}</div>
+                        </a>
                     @else
-                        @icon('lock'){{ trans('entities.shelves_permissions_active') }}
+                        <div class="entity-meta-item">
+                            @icon('lock')
+                            <div>{{ trans('entities.shelves_permissions_active') }}</div>
+                        </div>
                     @endif
                 </div>
             @endif
index 9ee5d4c056280c2aa78813247551be6672cf75cd..b18c182ebde971b6016d47836d333ad0a2b8fc6f 100644 (file)
@@ -19,7 +19,7 @@
                         <p class="small">{{ trans('settings.users_migrate_ownership_desc') }}</p>
                     </div>
                     <div>
-                        @include('form.user-select', ['name' => 'new_owner_id', 'user' => null, 'compact' => false])
+                        @include('form.user-select', ['name' => 'new_owner_id', 'user' => null])
                     </div>
                 </div>
             @endif
index 37f59b9706e5caf1ce9917846fb136555e42ccf1..5e16e5333e184f2f37a8f99b9e241a5deb0fd151 100644 (file)
@@ -82,6 +82,7 @@ Route::middleware('auth')->group(function () {
     Route::get('/books/{slug}/delete', [BookController::class, 'showDelete']);
     Route::get('/books/{bookSlug}/copy', [BookController::class, 'showCopy']);
     Route::post('/books/{bookSlug}/copy', [BookController::class, 'copy']);
+    Route::post('/books/{bookSlug}/convert-to-shelf', [BookController::class, 'convertToShelf']);
     Route::get('/books/{bookSlug}/sort', [BookSortController::class, 'show']);
     Route::put('/books/{bookSlug}/sort', [BookSortController::class, 'update']);
     Route::get('/books/{bookSlug}/export/html', [BookExportController::class, 'html']);
@@ -132,6 +133,7 @@ Route::middleware('auth')->group(function () {
     Route::get('/books/{bookSlug}/chapter/{chapterSlug}/copy', [ChapterController::class, 'showCopy']);
     Route::post('/books/{bookSlug}/chapter/{chapterSlug}/copy', [ChapterController::class, 'copy']);
     Route::get('/books/{bookSlug}/chapter/{chapterSlug}/edit', [ChapterController::class, 'edit']);
+    Route::post('/books/{bookSlug}/chapter/{chapterSlug}/convert-to-book', [ChapterController::class, 'convertToBook']);
     Route::get('/books/{bookSlug}/chapter/{chapterSlug}/permissions', [ChapterController::class, 'showPermissions']);
     Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/pdf', [ChapterExportController::class, 'pdf']);
     Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/html', [ChapterExportController::class, 'html']);
index 9fe8f8215bc6f201d26d669a360e28135228953a..f426cff7358fba2e54a4bbfa63dd82b18f20f7d8 100644 (file)
@@ -6,10 +6,12 @@ use BookStack\Entities\Models\Book;
 use Carbon\Carbon;
 use Illuminate\Support\Facades\DB;
 use Tests\TestCase;
+use Tests\Uploads\UsesImages;
 
 class BooksApiTest extends TestCase
 {
     use TestsApi;
+    use UsesImages;
 
     protected string $baseEndpoint = '/api/books';
 
@@ -118,6 +120,42 @@ class BooksApiTest extends TestCase
         $this->assertGreaterThan(Carbon::now()->subDay()->unix(), $book->updated_at->unix());
     }
 
+    public function test_update_cover_image_control()
+    {
+        $this->actingAsApiEditor();
+        /** @var Book $book */
+        $book = Book::visible()->first();
+        $this->assertNull($book->cover);
+        $file = $this->getTestImage('image.png');
+
+        // Ensure cover image can be set via API
+        $resp = $this->call('PUT', $this->baseEndpoint . "/{$book->id}", [
+            'name'  => 'My updated API book with image',
+        ], [], ['image' => $file]);
+        $book->refresh();
+
+        $resp->assertStatus(200);
+        $this->assertNotNull($book->cover);
+
+        // Ensure further updates without image do not clear cover image
+        $resp = $this->put($this->baseEndpoint . "/{$book->id}", [
+            'name' => 'My updated book again',
+        ]);
+        $book->refresh();
+
+        $resp->assertStatus(200);
+        $this->assertNotNull($book->cover);
+
+        // Ensure update with null image property clears image
+        $resp = $this->put($this->baseEndpoint . "/{$book->id}", [
+            'image' => null,
+        ]);
+        $book->refresh();
+
+        $resp->assertStatus(200);
+        $this->assertNull($book->cover);
+    }
+
     public function test_delete_endpoint()
     {
         $this->actingAsApiEditor();
index 034d4bc289eddf62194c75618c4e2f46323af201..bc7b6f16493a91f9091b04cf0b002599477b9865 100644 (file)
@@ -7,10 +7,12 @@ use BookStack\Entities\Models\Bookshelf;
 use Carbon\Carbon;
 use Illuminate\Support\Facades\DB;
 use Tests\TestCase;
+use Tests\Uploads\UsesImages;
 
 class ShelvesApiTest extends TestCase
 {
     use TestsApi;
+    use UsesImages;
 
     protected string $baseEndpoint = '/api/shelves';
 
@@ -146,6 +148,42 @@ class ShelvesApiTest extends TestCase
         $this->assertTrue($shelf->books()->count() === 0);
     }
 
+    public function test_update_cover_image_control()
+    {
+        $this->actingAsApiEditor();
+        /** @var Book $shelf */
+        $shelf = Bookshelf::visible()->first();
+        $this->assertNull($shelf->cover);
+        $file = $this->getTestImage('image.png');
+
+        // Ensure cover image can be set via API
+        $resp = $this->call('PUT', $this->baseEndpoint . "/{$shelf->id}", [
+            'name'  => 'My updated API shelf with image',
+        ], [], ['image' => $file]);
+        $shelf->refresh();
+
+        $resp->assertStatus(200);
+        $this->assertNotNull($shelf->cover);
+
+        // Ensure further updates without image do not clear cover image
+        $resp = $this->put($this->baseEndpoint . "/{$shelf->id}", [
+            'name' => 'My updated shelf again',
+        ]);
+        $shelf->refresh();
+
+        $resp->assertStatus(200);
+        $this->assertNotNull($shelf->cover);
+
+        // Ensure update with null image property clears image
+        $resp = $this->put($this->baseEndpoint . "/{$shelf->id}", [
+            'image' => null,
+        ]);
+        $shelf->refresh();
+
+        $resp->assertStatus(200);
+        $this->assertNull($shelf->cover);
+    }
+
     public function test_delete_endpoint()
     {
         $this->actingAsApiEditor();
diff --git a/tests/Auth/GroupSyncServiceTest.php b/tests/Auth/GroupSyncServiceTest.php
new file mode 100644 (file)
index 0000000..74d2c7e
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+
+namespace Tests\Auth;
+
+use BookStack\Auth\Access\GroupSyncService;
+use BookStack\Auth\Role;
+use BookStack\Auth\User;
+use Tests\TestCase;
+
+class GroupSyncServiceTest extends TestCase
+{
+    public function test_user_is_assigned_to_matching_roles()
+    {
+        $user = $this->getViewer();
+
+        $roleA = Role::factory()->create(['display_name' => 'Wizards']);
+        $roleB = Role::factory()->create(['display_name' => 'Gremlins']);
+        $roleC = Role::factory()->create(['display_name' => 'ABC123', 'external_auth_id' => 'sales']);
+        $roleD = Role::factory()->create(['display_name' => 'DEF456', 'external_auth_id' => 'admin-team']);
+
+        foreach ([$roleA, $roleB, $roleC, $roleD] as $role) {
+            $this->assertFalse($user->hasRole($role->id));
+        }
+
+        (new GroupSyncService())->syncUserWithFoundGroups($user, ['Wizards', 'Gremlinz', 'Sales', 'Admin Team'], false);
+
+        $user = User::query()->find($user->id);
+        $this->assertTrue($user->hasRole($roleA->id));
+        $this->assertFalse($user->hasRole($roleB->id));
+        $this->assertTrue($user->hasRole($roleC->id));
+        $this->assertTrue($user->hasRole($roleD->id));
+    }
+
+    public function test_multiple_values_in_role_external_auth_id_handled()
+    {
+        $user = $this->getViewer();
+        $role = Role::factory()->create(['display_name' => 'ABC123', 'external_auth_id' => 'sales, engineering, developers, marketers']);
+        $this->assertFalse($user->hasRole($role->id));
+
+        (new GroupSyncService())->syncUserWithFoundGroups($user, ['Developers'], false);
+
+        $user = User::query()->find($user->id);
+        $this->assertTrue($user->hasRole($role->id));
+    }
+
+    public function test_commas_can_be_used_in_external_auth_id_if_escaped()
+    {
+        $user = $this->getViewer();
+        $role = Role::factory()->create(['display_name' => 'ABC123', 'external_auth_id' => 'sales\,-developers, marketers']);
+        $this->assertFalse($user->hasRole($role->id));
+
+        (new GroupSyncService())->syncUserWithFoundGroups($user, ['Sales, Developers'], false);
+
+        $user = User::query()->find($user->id);
+        $this->assertTrue($user->hasRole($role->id));
+    }
+}
diff --git a/tests/Auth/LoginAutoInitiateTest.php b/tests/Auth/LoginAutoInitiateTest.php
new file mode 100644 (file)
index 0000000..86e1f93
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+
+namespace Tests\Auth;
+
+use Tests\TestCase;
+
+class LoginAutoInitiateTest extends TestCase
+{
+    protected function setUp(): void
+    {
+        parent::setUp();
+
+        config()->set([
+            'auth.auto_initiate'        => true,
+            'services.google.client_id' => false,
+            'services.github.client_id' => false,
+        ]);
+    }
+
+    public function test_with_oidc()
+    {
+        config()->set([
+            'auth.method' => 'oidc',
+        ]);
+
+        $req = $this->get('/login');
+        $req->assertSeeText('Attempting Login');
+        $req->assertElementExists('form[action$="/oidc/login"][method=POST][id="login-form"] button');
+        $req->assertElementExists('button[form="login-form"]');
+    }
+
+    public function test_with_saml2()
+    {
+        config()->set([
+            'auth.method' => 'saml2',
+        ]);
+
+        $req = $this->get('/login');
+        $req->assertSeeText('Attempting Login');
+        $req->assertElementExists('form[action$="/saml2/login"][method=POST][id="login-form"] button');
+        $req->assertElementExists('button[form="login-form"]');
+    }
+
+    public function test_it_does_not_run_if_social_provider_is_active()
+    {
+        config()->set([
+            'auth.method'                   => 'oidc',
+            'services.google.client_id'     => 'abc123a',
+            'services.google.client_secret' => 'def456',
+        ]);
+
+        $req = $this->get('/login');
+        $req->assertDontSeeText('Attempting Login');
+        $req->assertSee('Log In');
+    }
+
+    public function test_it_does_not_run_if_prevent_query_string_exists()
+    {
+        config()->set([
+            'auth.method' => 'oidc',
+        ]);
+
+        $req = $this->get('/login?prevent_auto_init=true');
+        $req->assertDontSeeText('Attempting Login');
+        $req->assertSee('Log In');
+    }
+
+    public function test_logout_with_auto_init_leads_to_login_page_with_prevention_query()
+    {
+        config()->set([
+            'auth.method' => 'oidc',
+        ]);
+        $this->actingAs($this->getEditor());
+
+        $req = $this->post('/logout');
+        $req->assertRedirect('/login?prevent_auto_init=true');
+    }
+}
index 9a6106243241d00e8cfd9c95b493ae1a62a49d9d..7286a1de8b997ee5dbc0295ac841a4e13da1fb3b 100644 (file)
@@ -241,6 +241,16 @@ class MfaVerificationTest extends TestCase
         }
     }
 
+    public function test_login_mfa_interception_does_not_log_error()
+    {
+        $logHandler = $this->withTestLogger();
+
+        [$user, $secret, $loginResp] = $this->startTotpLogin();
+
+        $loginResp->assertRedirect('/mfa/verify');
+        $this->assertFalse($logHandler->hasErrorRecords());
+    }
+
     /**
      * @return array<User, string, TestResponse>
      */
index 7f102a17eaede81e70792b8130f091444da0cdd9..8b2702b46e7c1bacfdcf72456cdd4a163a9f054f 100644 (file)
@@ -290,6 +290,7 @@ class BookTest extends TestCase
 
         /** @var Book $copy */
         $copy = Book::query()->where('name', '=', 'My copy book')->first();
+
         $this->assertNotNull($copy->cover);
         $this->assertNotEquals($book->cover->id, $copy->cover->id);
     }
diff --git a/tests/Entity/ConvertTest.php b/tests/Entity/ConvertTest.php
new file mode 100644 (file)
index 0000000..9791f77
--- /dev/null
@@ -0,0 +1,145 @@
+<?php
+
+namespace Tests\Entity;
+
+use BookStack\Actions\ActivityType;
+use BookStack\Actions\Tag;
+use BookStack\Entities\Models\Book;
+use BookStack\Entities\Models\Bookshelf;
+use BookStack\Entities\Models\Chapter;
+use BookStack\Entities\Models\Page;
+use Tests\TestCase;
+
+class ConvertTest extends TestCase
+{
+    public function test_chapter_edit_view_shows_convert_option()
+    {
+        /** @var Chapter $chapter */
+        $chapter = Chapter::query()->first();
+
+        $resp = $this->asEditor()->get($chapter->getUrl('/edit'));
+        $resp->assertSee('Convert to Book');
+        $resp->assertSee('Convert Chapter');
+        $resp->assertElementExists('form[action$="/convert-to-book"] button');
+    }
+
+    public function test_convert_chapter_to_book()
+    {
+        /** @var Chapter $chapter */
+        $chapter = Chapter::query()->whereHas('pages')->first();
+        $chapter->tags()->save(new Tag(['name' => 'Category', 'value' => 'Penguins']));
+        /** @var Page $childPage */
+        $childPage = $chapter->pages()->first();
+
+        $resp = $this->asEditor()->post($chapter->getUrl('/convert-to-book'));
+        $resp->assertRedirectContains('/books/');
+
+        /** @var Book $newBook */
+        $newBook = Book::query()->orderBy('id', 'desc')->first();
+
+        $this->assertDatabaseMissing('chapters', ['id' => $chapter->id]);
+        $this->assertDatabaseHas('pages', ['id' => $childPage->id, 'book_id' => $newBook->id, 'chapter_id' => 0]);
+        $this->assertCount(1, $newBook->tags);
+        $this->assertEquals('Category', $newBook->tags->first()->name);
+        $this->assertEquals('Penguins', $newBook->tags->first()->value);
+        $this->assertEquals($chapter->name, $newBook->name);
+        $this->assertEquals($chapter->description, $newBook->description);
+
+        $this->assertActivityExists(ActivityType::BOOK_CREATE_FROM_CHAPTER, $newBook);
+    }
+
+    public function test_convert_chapter_to_book_requires_permissions()
+    {
+        /** @var Chapter $chapter */
+        $chapter = Chapter::query()->first();
+        $user = $this->getViewer();
+
+        $permissions = ['chapter-delete-all', 'book-create-all', 'chapter-update-all'];
+        $this->giveUserPermissions($user, $permissions);
+
+        foreach ($permissions as $permission) {
+            $this->removePermissionFromUser($user, $permission);
+            $resp = $this->actingAs($user)->post($chapter->getUrl('/convert-to-book'));
+            $this->assertPermissionError($resp);
+            $this->giveUserPermissions($user, [$permission]);
+        }
+
+        $resp = $this->actingAs($user)->post($chapter->getUrl('/convert-to-book'));
+        $this->assertNotPermissionError($resp);
+        $resp->assertRedirect();
+    }
+
+    public function test_book_edit_view_shows_convert_option()
+    {
+        $book = Book::query()->first();
+
+        $resp = $this->asEditor()->get($book->getUrl('/edit'));
+        $resp->assertSee('Convert to Shelf');
+        $resp->assertSee('Convert Book');
+        $resp->assertSee('Note that permissions on shelves do not auto-cascade to content');
+        $resp->assertElementExists('form[action$="/convert-to-shelf"] button');
+    }
+
+    public function test_book_convert_to_shelf()
+    {
+        /** @var Book $book */
+        $book = Book::query()->whereHas('directPages')->whereHas('chapters')->firstOrFail();
+        $book->tags()->save(new Tag(['name' => 'Category', 'value' => 'Ducks']));
+        /** @var Page $childPage */
+        $childPage = $book->directPages()->first();
+        /** @var Chapter $childChapter */
+        $childChapter = $book->chapters()->whereHas('pages')->firstOrFail();
+        /** @var Page $chapterChildPage */
+        $chapterChildPage = $childChapter->pages()->firstOrFail();
+        $bookChapterCount = $book->chapters()->count();
+        $systemBookCount = Book::query()->count();
+
+        // Run conversion
+        $resp = $this->asEditor()->post($book->getUrl('/convert-to-shelf'));
+
+        /** @var Bookshelf $newShelf */
+        $newShelf = Bookshelf::query()->orderBy('id', 'desc')->first();
+
+        // Checks for new shelf
+        $resp->assertRedirectContains('/shelves/');
+        $this->assertDatabaseMissing('chapters', ['id' => $childChapter->id]);
+        $this->assertCount(1, $newShelf->tags);
+        $this->assertEquals('Category', $newShelf->tags->first()->name);
+        $this->assertEquals('Ducks', $newShelf->tags->first()->value);
+        $this->assertEquals($book->name, $newShelf->name);
+        $this->assertEquals($book->description, $newShelf->description);
+        $this->assertEquals($newShelf->books()->count(), $bookChapterCount + 1);
+        $this->assertEquals($systemBookCount + $bookChapterCount, Book::query()->count());
+        $this->assertActivityExists(ActivityType::BOOKSHELF_CREATE_FROM_BOOK, $newShelf);
+
+        // Checks for old book to contain child pages
+        $this->assertDatabaseHas('books', ['id' => $book->id, 'name' => $book->name . ' Pages']);
+        $this->assertDatabaseHas('pages', ['id' => $childPage->id, 'book_id' => $book->id, 'chapter_id' => 0]);
+
+        // Checks for nested page
+        $chapterChildPage->refresh();
+        $this->assertEquals(0, $chapterChildPage->chapter_id);
+        $this->assertEquals($childChapter->name, $chapterChildPage->book->name);
+    }
+
+    public function test_book_convert_to_shelf_requires_permissions()
+    {
+        /** @var Book $book */
+        $book = Book::query()->first();
+        $user = $this->getViewer();
+
+        $permissions = ['book-delete-all', 'bookshelf-create-all', 'book-update-all', 'book-create-all'];
+        $this->giveUserPermissions($user, $permissions);
+
+        foreach ($permissions as $permission) {
+            $this->removePermissionFromUser($user, $permission);
+            $resp = $this->actingAs($user)->post($book->getUrl('/convert-to-shelf'));
+            $this->assertPermissionError($resp);
+            $this->giveUserPermissions($user, [$permission]);
+        }
+
+        $resp = $this->actingAs($user)->post($book->getUrl('/convert-to-shelf'));
+        $this->assertNotPermissionError($resp);
+        $resp->assertRedirect();
+    }
+}
index ab5777e98981e9ec9c7e77db546b48b47ec07c47..b535f5aaa7e177d08efb4717c5c761410aa1732d 100644 (file)
@@ -423,6 +423,17 @@ class EntitySearchTest extends TestCase
         $search->assertSee('My supercool &lt;great&gt; <strong>TestPageContent</strong> page', false);
     }
 
+    public function test_words_adjacent_to_lines_breaks_can_be_matched_with_normal_terms()
+    {
+        $page = $this->newPage(['name' => 'TermA', 'html' => '
+            <p>TermA<br>TermB<br>TermC</p>
+        ']);
+
+        $search = $this->asEditor()->get('/search?term=' . urlencode('TermB TermC'));
+
+        $search->assertSee($page->getUrl(), false);
+    }
+
     public function test_searches_with_user_filters_adds_them_into_advanced_search_form()
     {
         $resp = $this->asEditor()->get('/search?term=' . urlencode('test {updated_by:me} {created_by:dan}'));
index 08d0921111fdb88a908867af8f228a9c1280e175..826b69be5d22b307882ba9e4385fd85d599c8a99 100644 (file)
@@ -457,4 +457,12 @@ class ExportTest extends TestCase
             $resp->assertElementExists('head meta[http-equiv="Content-Security-Policy"][content*="script-src "]');
         }
     }
+
+    public function test_html_exports_contain_body_classes_for_export_identification()
+    {
+        $page = Page::query()->first();
+
+        $resp = $this->asEditor()->get($page->getUrl('/export/html'));
+        $resp->assertElementExists('body.export.export-format-html.export-engine-none');
+    }
 }
index 17a5aa2c56faaf50cb4e9fbd6ad5ca828cba76a1..43389ad787ccc245a9b1d6d980f790c723a09038 100644 (file)
@@ -6,8 +6,8 @@ use BookStack\Entities\Models\Book;
 use BookStack\Entities\Models\Bookshelf;
 use BookStack\Entities\Models\Chapter;
 use BookStack\Entities\Models\Page;
+use BookStack\Entities\Repos\BaseRepo;
 use BookStack\Entities\Repos\BookRepo;
-use BookStack\Entities\Repos\BookshelfRepo;
 use Illuminate\Support\Str;
 use Tests\Uploads\UsesImages;
 
@@ -69,8 +69,8 @@ class OpenGraphTest extends TestCase
         $this->assertArrayNotHasKey('image', $tags);
 
         // Test image set if image has cover image
-        $shelfRepo = app(BookshelfRepo::class);
-        $shelfRepo->updateCoverImage($shelf, $this->getTestImage('image.png'));
+        $baseRepo = app(BaseRepo::class);
+        $baseRepo->updateCoverImage($shelf, $this->getTestImage('image.png'));
         $resp = $this->asEditor()->get($shelf->getUrl());
         $tags = $this->getOpenGraphTags($resp);
 
index cbf49bf71f424f747e97bc04b3e3ff55fa6bb50b..ce57d56f51d0f473e73e6f63642997e11a7424fe 100644 (file)
@@ -194,13 +194,23 @@ trait SharedTestHelpers
     /**
      * Completely remove the given permission name from the given user.
      */
-    protected function removePermissionFromUser(User $user, string $permission)
+    protected function removePermissionFromUser(User $user, string $permissionName)
     {
-        $permission = RolePermission::query()->where('name', '=', $permission)->first();
+        $permissionService = app()->make(PermissionService::class);
+
+        /** @var RolePermission $permission */
+        $permission = RolePermission::query()->where('name', '=', $permissionName)->firstOrFail();
+
+        $roles = $user->roles()->whereHas('permissions', function ($query) use ($permission) {
+            $query->where('id', '=', $permission->id);
+        })->get();
+
         /** @var Role $role */
-        foreach ($user->roles as $role) {
+        foreach ($roles as $role) {
             $role->detachPermission($permission);
+            $permissionService->buildJointPermissionForRole($role);
         }
+
         $user->clearPermissionCache();
     }
 
index 4e53aa020ba3ca5054e8d75e14a2ed57dc277276..888bacdfc6c0152f9be22d498c9fd348f90a552c 100644 (file)
@@ -111,7 +111,7 @@ class TestResponse extends BaseTestResponse
 
         foreach ($elements as $element) {
             $element = new Crawler($element);
-            if (preg_match("/$pattern/i", $element->html())) {
+            if (preg_match("/$pattern/i", $element->text())) {
                 $matched = true;
                 break;
             }
index cad2369f8bec50825e626052d52947d3b8b33b05..85b8b9d364135e564f29415755d9518b52eee51c 100644 (file)
@@ -254,6 +254,23 @@ class ThemeTest extends TestCase
         $this->assertStringContainsString('Command ran!', $output);
     }
 
+    public function test_body_start_and_end_template_files_can_be_used()
+    {
+        $bodyStartStr = 'barry-fought-against-the-panther';
+        $bodyEndStr = 'barry-lost-his-fight-with-grace';
+
+        $this->usingThemeFolder(function (string $folder) use ($bodyStartStr, $bodyEndStr) {
+            $viewDir = theme_path('layouts/parts');
+            mkdir($viewDir, 0777, true);
+            file_put_contents($viewDir . '/base-body-start.blade.php', $bodyStartStr);
+            file_put_contents($viewDir . '/base-body-end.blade.php', $bodyEndStr);
+
+            $resp = $this->asEditor()->get('/');
+            $resp->assertSee($bodyStartStr);
+            $resp->assertSee($bodyEndStr);
+        });
+    }
+
     protected function usingThemeFolder(callable $callback)
     {
         // Create a folder and configure a theme
@@ -262,7 +279,10 @@ class ThemeTest extends TestCase
         $themeFolderPath = theme_path('');
         File::makeDirectory($themeFolderPath);
 
-        call_user_func($callback, $themeFolderName);
+        // Run provided callback with theme env option set
+        $this->runWithEnv('APP_THEME', $themeFolderName, function () use ($callback, $themeFolderName) {
+            call_user_func($callback, $themeFolderName);
+        });
 
         // Cleanup the custom theme folder we created
         File::deleteDirectory($themeFolderPath);
diff --git a/version b/version
index c94b1a5984033fd4b685a6034446ca5da73cf50c..eee08ef7617871204c7a8a771013f311ee470086 100644 (file)
--- a/version
+++ b/version
@@ -1 +1 @@
-v22.04.2
+v22.06-dev