mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-08-07 23:03:00 +03:00
Merge branch 'development' into release
This commit is contained in:
7
.github/translators.txt
vendored
7
.github/translators.txt
vendored
@@ -493,3 +493,10 @@ Angel Pandey (angel-pandey) :: Nepali
|
||||
Supriya Shrestha (supriyashrestha) :: Nepali
|
||||
gprabhat :: Nepali
|
||||
CellCat :: Chinese Simplified
|
||||
Al Desrahim (aldesrahim) :: Indonesian
|
||||
ahmad abbaspour (deshneh.dar.diss) :: Persian
|
||||
Erjon K. (ekr) :: Albanian
|
||||
LiZerui (iamzrli) :: Chinese Traditional
|
||||
Ticker (ticker.com) :: Hebrew
|
||||
CrazyComputer :: Chinese Simplified
|
||||
Firr (FirrV) :: Russian
|
||||
|
@@ -12,6 +12,8 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $value
|
||||
* @property int $entity_id
|
||||
* @property string $entity_type
|
||||
* @property int $order
|
||||
*/
|
||||
class Tag extends Model
|
||||
|
@@ -3,17 +3,15 @@
|
||||
namespace BookStack\Activity\Tools;
|
||||
|
||||
use BookStack\Activity\Models\Tag;
|
||||
use BookStack\Entities\Models\BookChild;
|
||||
use BookStack\Entities\Models\Entity;
|
||||
use BookStack\Entities\Models\Page;
|
||||
|
||||
class TagClassGenerator
|
||||
{
|
||||
protected array $tags;
|
||||
|
||||
/**
|
||||
* @param Tag[] $tags
|
||||
*/
|
||||
public function __construct(array $tags)
|
||||
{
|
||||
$this->tags = $tags;
|
||||
public function __construct(
|
||||
protected Entity $entity
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -22,14 +20,23 @@ class TagClassGenerator
|
||||
public function generate(): array
|
||||
{
|
||||
$classes = [];
|
||||
$tags = $this->entity->tags->all();
|
||||
|
||||
foreach ($this->tags as $tag) {
|
||||
$name = $this->normalizeTagClassString($tag->name);
|
||||
$value = $this->normalizeTagClassString($tag->value);
|
||||
$classes[] = 'tag-name-' . $name;
|
||||
if ($value) {
|
||||
$classes[] = 'tag-value-' . $value;
|
||||
$classes[] = 'tag-pair-' . $name . '-' . $value;
|
||||
foreach ($tags as $tag) {
|
||||
array_push($classes, ...$this->generateClassesForTag($tag));
|
||||
}
|
||||
|
||||
if ($this->entity instanceof BookChild && userCan('view', $this->entity->book)) {
|
||||
$bookTags = $this->entity->book->tags;
|
||||
foreach ($bookTags as $bookTag) {
|
||||
array_push($classes, ...$this->generateClassesForTag($bookTag, 'book-'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->entity instanceof Page && $this->entity->chapter && userCan('view', $this->entity->chapter)) {
|
||||
$chapterTags = $this->entity->chapter->tags;
|
||||
foreach ($chapterTags as $chapterTag) {
|
||||
array_push($classes, ...$this->generateClassesForTag($chapterTag, 'chapter-'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +48,22 @@ class TagClassGenerator
|
||||
return implode(' ', $this->generate());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected function generateClassesForTag(Tag $tag, string $prefix = ''): array
|
||||
{
|
||||
$classes = [];
|
||||
$name = $this->normalizeTagClassString($tag->name);
|
||||
$value = $this->normalizeTagClassString($tag->value);
|
||||
$classes[] = "{$prefix}tag-name-{$name}";
|
||||
if ($value) {
|
||||
$classes[] = "{$prefix}tag-value-{$value}";
|
||||
$classes[] = "{$prefix}tag-pair-{$name}-{$value}";
|
||||
}
|
||||
return $classes;
|
||||
}
|
||||
|
||||
protected function normalizeTagClassString(string $value): string
|
||||
{
|
||||
$value = str_replace(' ', '', strtolower($value));
|
||||
|
@@ -11,6 +11,7 @@
|
||||
// Configured mail encryption method.
|
||||
// STARTTLS should still be attempted, but tls/ssl forces TLS usage.
|
||||
$mailEncryption = env('MAIL_ENCRYPTION', null);
|
||||
$mailPort = intval(env('MAIL_PORT', 587));
|
||||
|
||||
return [
|
||||
|
||||
@@ -33,13 +34,13 @@ return [
|
||||
'transport' => 'smtp',
|
||||
'scheme' => null,
|
||||
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
|
||||
'port' => env('MAIL_PORT', 587),
|
||||
'port' => $mailPort,
|
||||
'username' => env('MAIL_USERNAME'),
|
||||
'password' => env('MAIL_PASSWORD'),
|
||||
'verify_peer' => env('MAIL_VERIFY_SSL', true),
|
||||
'timeout' => null,
|
||||
'local_domain' => null,
|
||||
'tls_required' => ($mailEncryption === 'tls' || $mailEncryption === 'ssl'),
|
||||
'require_tls' => ($mailEncryption === 'tls' || $mailEncryption === 'ssl' || $mailPort === 465),
|
||||
],
|
||||
|
||||
'sendmail' => [
|
||||
|
@@ -18,6 +18,7 @@ use BookStack\Exceptions\NotFoundException;
|
||||
use BookStack\Facades\Activity;
|
||||
use BookStack\Http\Controller;
|
||||
use BookStack\References\ReferenceFetcher;
|
||||
use BookStack\Util\DatabaseTransaction;
|
||||
use BookStack\Util\SimpleListOptions;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
@@ -263,7 +264,9 @@ class BookController extends Controller
|
||||
$this->checkPermission('bookshelf-create-all');
|
||||
$this->checkPermission('book-create-all');
|
||||
|
||||
$shelf = $transformer->transformBookToShelf($book);
|
||||
$shelf = (new DatabaseTransaction(function () use ($book, $transformer) {
|
||||
return $transformer->transformBookToShelf($book);
|
||||
}))->run();
|
||||
|
||||
return redirect($shelf->getUrl());
|
||||
}
|
||||
|
@@ -9,12 +9,11 @@ use BookStack\Entities\Repos\ChapterRepo;
|
||||
use BookStack\Exceptions\PermissionsException;
|
||||
use BookStack\Http\ApiController;
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ChapterApiController extends ApiController
|
||||
{
|
||||
protected $rules = [
|
||||
protected array $rules = [
|
||||
'create' => [
|
||||
'book_id' => ['required', 'integer'],
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
|
@@ -18,6 +18,7 @@ use BookStack\Exceptions\NotifyException;
|
||||
use BookStack\Exceptions\PermissionsException;
|
||||
use BookStack\Http\Controller;
|
||||
use BookStack\References\ReferenceFetcher;
|
||||
use BookStack\Util\DatabaseTransaction;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Throwable;
|
||||
@@ -269,7 +270,9 @@ class ChapterController extends Controller
|
||||
$this->checkOwnablePermission('chapter-delete', $chapter);
|
||||
$this->checkPermission('book-create-all');
|
||||
|
||||
$book = $transformer->transformChapterToBook($chapter);
|
||||
$book = (new DatabaseTransaction(function () use ($chapter, $transformer) {
|
||||
return $transformer->transformChapterToBook($chapter);
|
||||
}))->run();
|
||||
|
||||
return redirect($book->getUrl());
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ use Illuminate\Http\Request;
|
||||
|
||||
class PageApiController extends ApiController
|
||||
{
|
||||
protected $rules = [
|
||||
protected array $rules = [
|
||||
'create' => [
|
||||
'book_id' => ['required_without:chapter_id', 'integer'],
|
||||
'chapter_id' => ['required_without:book_id', 'integer'],
|
||||
|
@@ -77,7 +77,6 @@ class BaseRepo
|
||||
$entity->touch();
|
||||
}
|
||||
|
||||
$entity->rebuildPermissions();
|
||||
$entity->indexForSearch();
|
||||
$this->referenceStore->updateForEntity($entity);
|
||||
|
||||
@@ -139,7 +138,7 @@ class BaseRepo
|
||||
|
||||
/**
|
||||
* Sort the parent of the given entity, if any auto sort actions are set for it.
|
||||
* Typical ran during create/update/insert events.
|
||||
* Typically ran during create/update/insert events.
|
||||
*/
|
||||
public function sortParent(Entity $entity): void
|
||||
{
|
||||
|
@@ -10,6 +10,7 @@ use BookStack\Exceptions\ImageUploadException;
|
||||
use BookStack\Facades\Activity;
|
||||
use BookStack\Sorting\SortRule;
|
||||
use BookStack\Uploads\ImageRepo;
|
||||
use BookStack\Util\DatabaseTransaction;
|
||||
use Exception;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
|
||||
@@ -28,19 +29,22 @@ class BookRepo
|
||||
*/
|
||||
public function create(array $input): Book
|
||||
{
|
||||
$book = new Book();
|
||||
$this->baseRepo->create($book, $input);
|
||||
$this->baseRepo->updateCoverImage($book, $input['image'] ?? null);
|
||||
$this->baseRepo->updateDefaultTemplate($book, intval($input['default_template_id'] ?? null));
|
||||
Activity::add(ActivityType::BOOK_CREATE, $book);
|
||||
return (new DatabaseTransaction(function () use ($input) {
|
||||
$book = new Book();
|
||||
|
||||
$defaultBookSortSetting = intval(setting('sorting-book-default', '0'));
|
||||
if ($defaultBookSortSetting && SortRule::query()->find($defaultBookSortSetting)) {
|
||||
$book->sort_rule_id = $defaultBookSortSetting;
|
||||
$book->save();
|
||||
}
|
||||
$this->baseRepo->create($book, $input);
|
||||
$this->baseRepo->updateCoverImage($book, $input['image'] ?? null);
|
||||
$this->baseRepo->updateDefaultTemplate($book, intval($input['default_template_id'] ?? null));
|
||||
Activity::add(ActivityType::BOOK_CREATE, $book);
|
||||
|
||||
return $book;
|
||||
$defaultBookSortSetting = intval(setting('sorting-book-default', '0'));
|
||||
if ($defaultBookSortSetting && SortRule::query()->find($defaultBookSortSetting)) {
|
||||
$book->sort_rule_id = $defaultBookSortSetting;
|
||||
$book->save();
|
||||
}
|
||||
|
||||
return $book;
|
||||
}))->run();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -7,6 +7,7 @@ use BookStack\Entities\Models\Bookshelf;
|
||||
use BookStack\Entities\Queries\BookQueries;
|
||||
use BookStack\Entities\Tools\TrashCan;
|
||||
use BookStack\Facades\Activity;
|
||||
use BookStack\Util\DatabaseTransaction;
|
||||
use Exception;
|
||||
|
||||
class BookshelfRepo
|
||||
@@ -23,13 +24,14 @@ class BookshelfRepo
|
||||
*/
|
||||
public function create(array $input, array $bookIds): Bookshelf
|
||||
{
|
||||
$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);
|
||||
|
||||
return $shelf;
|
||||
return (new DatabaseTransaction(function () use ($input, $bookIds) {
|
||||
$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);
|
||||
return $shelf;
|
||||
}))->run();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -11,6 +11,7 @@ use BookStack\Entities\Tools\TrashCan;
|
||||
use BookStack\Exceptions\MoveOperationException;
|
||||
use BookStack\Exceptions\PermissionsException;
|
||||
use BookStack\Facades\Activity;
|
||||
use BookStack\Util\DatabaseTransaction;
|
||||
use Exception;
|
||||
|
||||
class ChapterRepo
|
||||
@@ -27,16 +28,18 @@ class ChapterRepo
|
||||
*/
|
||||
public function create(array $input, Book $parentBook): Chapter
|
||||
{
|
||||
$chapter = new Chapter();
|
||||
$chapter->book_id = $parentBook->id;
|
||||
$chapter->priority = (new BookContents($parentBook))->getLastPriority() + 1;
|
||||
$this->baseRepo->create($chapter, $input);
|
||||
$this->baseRepo->updateDefaultTemplate($chapter, intval($input['default_template_id'] ?? null));
|
||||
Activity::add(ActivityType::CHAPTER_CREATE, $chapter);
|
||||
return (new DatabaseTransaction(function () use ($input, $parentBook) {
|
||||
$chapter = new Chapter();
|
||||
$chapter->book_id = $parentBook->id;
|
||||
$chapter->priority = (new BookContents($parentBook))->getLastPriority() + 1;
|
||||
$this->baseRepo->create($chapter, $input);
|
||||
$this->baseRepo->updateDefaultTemplate($chapter, intval($input['default_template_id'] ?? null));
|
||||
Activity::add(ActivityType::CHAPTER_CREATE, $chapter);
|
||||
|
||||
$this->baseRepo->sortParent($chapter);
|
||||
$this->baseRepo->sortParent($chapter);
|
||||
|
||||
return $chapter;
|
||||
return $chapter;
|
||||
}))->run();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,12 +91,14 @@ class ChapterRepo
|
||||
throw new PermissionsException('User does not have permission to create a chapter within the chosen book');
|
||||
}
|
||||
|
||||
$chapter->changeBook($parent->id);
|
||||
$chapter->rebuildPermissions();
|
||||
Activity::add(ActivityType::CHAPTER_MOVE, $chapter);
|
||||
return (new DatabaseTransaction(function () use ($chapter, $parent) {
|
||||
$chapter->changeBook($parent->id);
|
||||
$chapter->rebuildPermissions();
|
||||
Activity::add(ActivityType::CHAPTER_MOVE, $chapter);
|
||||
|
||||
$this->baseRepo->sortParent($chapter);
|
||||
$this->baseRepo->sortParent($chapter);
|
||||
|
||||
return $parent;
|
||||
return $parent;
|
||||
}))->run();
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ use BookStack\Exceptions\PermissionsException;
|
||||
use BookStack\Facades\Activity;
|
||||
use BookStack\References\ReferenceStore;
|
||||
use BookStack\References\ReferenceUpdater;
|
||||
use BookStack\Util\DatabaseTransaction;
|
||||
use Exception;
|
||||
|
||||
class PageRepo
|
||||
@@ -61,8 +62,10 @@ class PageRepo
|
||||
]);
|
||||
}
|
||||
|
||||
$page->save();
|
||||
$page->refresh()->rebuildPermissions();
|
||||
(new DatabaseTransaction(function () use ($page) {
|
||||
$page->save();
|
||||
$page->refresh()->rebuildPermissions();
|
||||
}))->run();
|
||||
|
||||
return $page;
|
||||
}
|
||||
@@ -72,26 +75,29 @@ class PageRepo
|
||||
*/
|
||||
public function publishDraft(Page $draft, array $input): Page
|
||||
{
|
||||
$draft->draft = false;
|
||||
$draft->revision_count = 1;
|
||||
$draft->priority = $this->getNewPriority($draft);
|
||||
$this->updateTemplateStatusAndContentFromInput($draft, $input);
|
||||
$this->baseRepo->update($draft, $input);
|
||||
return (new DatabaseTransaction(function () use ($draft, $input) {
|
||||
$draft->draft = false;
|
||||
$draft->revision_count = 1;
|
||||
$draft->priority = $this->getNewPriority($draft);
|
||||
$this->updateTemplateStatusAndContentFromInput($draft, $input);
|
||||
$this->baseRepo->update($draft, $input);
|
||||
$draft->rebuildPermissions();
|
||||
|
||||
$summary = trim($input['summary'] ?? '') ?: trans('entities.pages_initial_revision');
|
||||
$this->revisionRepo->storeNewForPage($draft, $summary);
|
||||
$draft->refresh();
|
||||
$summary = trim($input['summary'] ?? '') ?: trans('entities.pages_initial_revision');
|
||||
$this->revisionRepo->storeNewForPage($draft, $summary);
|
||||
$draft->refresh();
|
||||
|
||||
Activity::add(ActivityType::PAGE_CREATE, $draft);
|
||||
$this->baseRepo->sortParent($draft);
|
||||
Activity::add(ActivityType::PAGE_CREATE, $draft);
|
||||
$this->baseRepo->sortParent($draft);
|
||||
|
||||
return $draft;
|
||||
return $draft;
|
||||
}))->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Directly update the content for the given page from the provided input.
|
||||
* Used for direct content access in a way that performs required changes
|
||||
* (Search index & reference regen) without performing an official update.
|
||||
* (Search index and reference regen) without performing an official update.
|
||||
*/
|
||||
public function setContentFromInput(Page $page, array $input): void
|
||||
{
|
||||
@@ -116,7 +122,7 @@ class PageRepo
|
||||
$page->revision_count++;
|
||||
$page->save();
|
||||
|
||||
// Remove all update drafts for this user & page.
|
||||
// Remove all update drafts for this user and page.
|
||||
$this->revisionRepo->deleteDraftsForCurrentUser($page);
|
||||
|
||||
// Save a revision after updating
|
||||
@@ -269,16 +275,18 @@ class PageRepo
|
||||
throw new PermissionsException('User does not have permission to create a page within the new parent');
|
||||
}
|
||||
|
||||
$page->chapter_id = ($parent instanceof Chapter) ? $parent->id : null;
|
||||
$newBookId = ($parent instanceof Chapter) ? $parent->book->id : $parent->id;
|
||||
$page->changeBook($newBookId);
|
||||
$page->rebuildPermissions();
|
||||
return (new DatabaseTransaction(function () use ($page, $parent) {
|
||||
$page->chapter_id = ($parent instanceof Chapter) ? $parent->id : null;
|
||||
$newBookId = ($parent instanceof Chapter) ? $parent->book->id : $parent->id;
|
||||
$page->changeBook($newBookId);
|
||||
$page->rebuildPermissions();
|
||||
|
||||
Activity::add(ActivityType::PAGE_MOVE, $page);
|
||||
Activity::add(ActivityType::PAGE_MOVE, $page);
|
||||
|
||||
$this->baseRepo->sortParent($page);
|
||||
$this->baseRepo->sortParent($page);
|
||||
|
||||
return $parent;
|
||||
return $parent;
|
||||
}))->run();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -13,17 +13,12 @@ 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;
|
||||
public function __construct(
|
||||
protected BookRepo $bookRepo,
|
||||
protected BookshelfRepo $shelfRepo,
|
||||
protected Cloner $cloner,
|
||||
protected TrashCan $trashCan
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -15,6 +15,7 @@ use BookStack\Exceptions\NotifyException;
|
||||
use BookStack\Facades\Activity;
|
||||
use BookStack\Uploads\AttachmentService;
|
||||
use BookStack\Uploads\ImageService;
|
||||
use BookStack\Util\DatabaseTransaction;
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Carbon;
|
||||
@@ -357,25 +358,26 @@ class TrashCan
|
||||
|
||||
/**
|
||||
* Destroy the given entity.
|
||||
* Returns the number of total entities destroyed in the operation.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function destroyEntity(Entity $entity): int
|
||||
{
|
||||
if ($entity instanceof Page) {
|
||||
return $this->destroyPage($entity);
|
||||
}
|
||||
if ($entity instanceof Chapter) {
|
||||
return $this->destroyChapter($entity);
|
||||
}
|
||||
if ($entity instanceof Book) {
|
||||
return $this->destroyBook($entity);
|
||||
}
|
||||
if ($entity instanceof Bookshelf) {
|
||||
return $this->destroyShelf($entity);
|
||||
}
|
||||
$result = (new DatabaseTransaction(function () use ($entity) {
|
||||
if ($entity instanceof Page) {
|
||||
return $this->destroyPage($entity);
|
||||
} else if ($entity instanceof Chapter) {
|
||||
return $this->destroyChapter($entity);
|
||||
} else if ($entity instanceof Book) {
|
||||
return $this->destroyBook($entity);
|
||||
} else if ($entity instanceof Bookshelf) {
|
||||
return $this->destroyShelf($entity);
|
||||
}
|
||||
return null;
|
||||
}))->run();
|
||||
|
||||
return 0;
|
||||
return $result ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -4,6 +4,7 @@ namespace BookStack\Exports\Controllers;
|
||||
|
||||
use BookStack\Entities\Queries\BookQueries;
|
||||
use BookStack\Exports\ExportFormatter;
|
||||
use BookStack\Exports\ZipExports\ZipExportBuilder;
|
||||
use BookStack\Http\ApiController;
|
||||
use Throwable;
|
||||
|
||||
@@ -63,4 +64,15 @@ class BookExportApiController extends ApiController
|
||||
|
||||
return $this->download()->directly($markdown, $book->slug . '.md');
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a book as a contained ZIP export file.
|
||||
*/
|
||||
public function exportZip(int $id, ZipExportBuilder $builder)
|
||||
{
|
||||
$book = $this->queries->findVisibleByIdOrFail($id);
|
||||
$zip = $builder->buildForBook($book);
|
||||
|
||||
return $this->download()->streamedFileDirectly($zip, $book->slug . '.zip', true);
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ namespace BookStack\Exports\Controllers;
|
||||
|
||||
use BookStack\Entities\Queries\ChapterQueries;
|
||||
use BookStack\Exports\ExportFormatter;
|
||||
use BookStack\Exports\ZipExports\ZipExportBuilder;
|
||||
use BookStack\Http\ApiController;
|
||||
use Throwable;
|
||||
|
||||
@@ -63,4 +64,15 @@ class ChapterExportApiController extends ApiController
|
||||
|
||||
return $this->download()->directly($markdown, $chapter->slug . '.md');
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a chapter as a contained ZIP file.
|
||||
*/
|
||||
public function exportZip(int $id, ZipExportBuilder $builder)
|
||||
{
|
||||
$chapter = $this->queries->findVisibleByIdOrFail($id);
|
||||
$zip = $builder->buildForChapter($chapter);
|
||||
|
||||
return $this->download()->streamedFileDirectly($zip, $chapter->slug . '.zip', true);
|
||||
}
|
||||
}
|
||||
|
144
app/Exports/Controllers/ImportApiController.php
Normal file
144
app/Exports/Controllers/ImportApiController.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BookStack\Exports\Controllers;
|
||||
|
||||
use BookStack\Exceptions\ZipImportException;
|
||||
use BookStack\Exceptions\ZipValidationException;
|
||||
use BookStack\Exports\ImportRepo;
|
||||
use BookStack\Http\ApiController;
|
||||
use BookStack\Uploads\AttachmentService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class ImportApiController extends ApiController
|
||||
{
|
||||
public function __construct(
|
||||
protected ImportRepo $imports,
|
||||
) {
|
||||
$this->middleware('can:content-import');
|
||||
}
|
||||
|
||||
/**
|
||||
* List existing ZIP imports visible to the user.
|
||||
* Requires permission to import content.
|
||||
*/
|
||||
public function list(): JsonResponse
|
||||
{
|
||||
$query = $this->imports->queryVisible();
|
||||
|
||||
return $this->apiListingResponse($query, [
|
||||
'id', 'name', 'size', 'type', 'created_by', 'created_at', 'updated_at'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new import from a ZIP file.
|
||||
* This does not actually run the import since that is performed via the "run" endpoint.
|
||||
* This uploads, validates and stores the ZIP file so it's ready to be imported.
|
||||
*
|
||||
* This "file" parameter must be a BookStack-compatible ZIP file, and this must be
|
||||
* sent via a 'multipart/form-data' type request.
|
||||
*
|
||||
* Requires permission to import content.
|
||||
*/
|
||||
public function create(Request $request): JsonResponse
|
||||
{
|
||||
$this->validate($request, $this->rules()['create']);
|
||||
|
||||
$file = $request->file('file');
|
||||
|
||||
try {
|
||||
$import = $this->imports->storeFromUpload($file);
|
||||
} catch (ZipValidationException $exception) {
|
||||
$message = "ZIP upload failed with the following validation errors: \n" . $this->formatErrors($exception->errors);
|
||||
return $this->jsonError($message, 422);
|
||||
}
|
||||
|
||||
return response()->json($import);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read details of a pending ZIP import.
|
||||
* The "details" property contains high-level metadata regarding the ZIP import content,
|
||||
* and the structure of this will change depending on import "type".
|
||||
* Requires permission to import content.
|
||||
*/
|
||||
public function read(int $id): JsonResponse
|
||||
{
|
||||
$import = $this->imports->findVisible($id);
|
||||
|
||||
$import->setAttribute('details', $import->decodeMetadata());
|
||||
|
||||
return response()->json($import);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the import process for an uploaded ZIP import.
|
||||
* The "parent_id" and "parent_type" parameters are required when the import type is "chapter" or "page".
|
||||
* On success, this endpoint returns the imported item.
|
||||
* Requires permission to import content.
|
||||
*/
|
||||
public function run(int $id, Request $request): JsonResponse
|
||||
{
|
||||
$import = $this->imports->findVisible($id);
|
||||
$parent = null;
|
||||
$rules = $this->rules()['run'];
|
||||
|
||||
if ($import->type === 'page' || $import->type === 'chapter') {
|
||||
$rules['parent_type'][] = 'required';
|
||||
$rules['parent_id'][] = 'required';
|
||||
$data = $this->validate($request, $rules);
|
||||
$parent = "{$data['parent_type']}:{$data['parent_id']}";
|
||||
}
|
||||
|
||||
try {
|
||||
$entity = $this->imports->runImport($import, $parent);
|
||||
} catch (ZipImportException $exception) {
|
||||
$message = "ZIP import failed with the following errors: \n" . $this->formatErrors($exception->errors);
|
||||
return $this->jsonError($message);
|
||||
}
|
||||
|
||||
return response()->json($entity->withoutRelations());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a pending ZIP import from the system.
|
||||
* Requires permission to import content.
|
||||
*/
|
||||
public function delete(int $id): Response
|
||||
{
|
||||
$import = $this->imports->findVisible($id);
|
||||
$this->imports->deleteImport($import);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
protected function rules(): array
|
||||
{
|
||||
return [
|
||||
'create' => [
|
||||
'file' => ['required', ...AttachmentService::getFileValidationRules()],
|
||||
],
|
||||
'run' => [
|
||||
'parent_type' => ['string', 'in:book,chapter'],
|
||||
'parent_id' => ['int'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
protected function formatErrors(array $errors): string
|
||||
{
|
||||
$parts = [];
|
||||
foreach ($errors as $key => $error) {
|
||||
if (is_string($key)) {
|
||||
$parts[] = "[{$key}] {$error}";
|
||||
} else {
|
||||
$parts[] = $error;
|
||||
}
|
||||
}
|
||||
return implode("\n", $parts);
|
||||
}
|
||||
}
|
@@ -4,6 +4,7 @@ namespace BookStack\Exports\Controllers;
|
||||
|
||||
use BookStack\Entities\Queries\PageQueries;
|
||||
use BookStack\Exports\ExportFormatter;
|
||||
use BookStack\Exports\ZipExports\ZipExportBuilder;
|
||||
use BookStack\Http\ApiController;
|
||||
use Throwable;
|
||||
|
||||
@@ -63,4 +64,15 @@ class PageExportApiController extends ApiController
|
||||
|
||||
return $this->download()->directly($markdown, $page->slug . '.md');
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a page as a contained ZIP file.
|
||||
*/
|
||||
public function exportZip(int $id, ZipExportBuilder $builder)
|
||||
{
|
||||
$page = $this->queries->findVisibleByIdOrFail($id);
|
||||
$zip = $builder->buildForPage($page);
|
||||
|
||||
return $this->download()->streamedFileDirectly($zip, $page->slug . '.zip', true);
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,8 @@ class Import extends Model implements Loggable
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $hidden = ['metadata'];
|
||||
|
||||
public function getSizeString(): string
|
||||
{
|
||||
$mb = round($this->size / 1000000, 2);
|
||||
|
@@ -17,6 +17,7 @@ use BookStack\Exports\ZipExports\ZipExportValidator;
|
||||
use BookStack\Exports\ZipExports\ZipImportRunner;
|
||||
use BookStack\Facades\Activity;
|
||||
use BookStack\Uploads\FileStorage;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
@@ -34,6 +35,11 @@ class ImportRepo
|
||||
* @return Collection<Import>
|
||||
*/
|
||||
public function getVisibleImports(): Collection
|
||||
{
|
||||
return $this->queryVisible()->get();
|
||||
}
|
||||
|
||||
public function queryVisible(): Builder
|
||||
{
|
||||
$query = Import::query();
|
||||
|
||||
@@ -41,7 +47,7 @@ class ImportRepo
|
||||
$query->where('created_by', user()->id);
|
||||
}
|
||||
|
||||
return $query->get();
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function findVisible(int $id): Import
|
||||
|
@@ -8,7 +8,7 @@ use Illuminate\Http\JsonResponse;
|
||||
|
||||
abstract class ApiController extends Controller
|
||||
{
|
||||
protected $rules = [];
|
||||
protected array $rules = [];
|
||||
|
||||
/**
|
||||
* Provide a paginated listing JSON response in a standard format
|
||||
|
@@ -16,7 +16,7 @@ class ContentPermissionApiController extends ApiController
|
||||
) {
|
||||
}
|
||||
|
||||
protected $rules = [
|
||||
protected array $rules = [
|
||||
'update' => [
|
||||
'owner_id' => ['int'],
|
||||
|
||||
|
@@ -29,7 +29,7 @@ class JointPermissionBuilder
|
||||
/**
|
||||
* Re-generate all entity permission from scratch.
|
||||
*/
|
||||
public function rebuildForAll()
|
||||
public function rebuildForAll(): void
|
||||
{
|
||||
JointPermission::query()->truncate();
|
||||
|
||||
@@ -51,7 +51,7 @@ class JointPermissionBuilder
|
||||
/**
|
||||
* Rebuild the entity jointPermissions for a particular entity.
|
||||
*/
|
||||
public function rebuildForEntity(Entity $entity)
|
||||
public function rebuildForEntity(Entity $entity): void
|
||||
{
|
||||
$entities = [$entity];
|
||||
if ($entity instanceof Book) {
|
||||
@@ -119,7 +119,7 @@ class JointPermissionBuilder
|
||||
/**
|
||||
* Build joint permissions for the given book and role combinations.
|
||||
*/
|
||||
protected function buildJointPermissionsForBooks(EloquentCollection $books, array $roles, bool $deleteOld = false)
|
||||
protected function buildJointPermissionsForBooks(EloquentCollection $books, array $roles, bool $deleteOld = false): void
|
||||
{
|
||||
$entities = clone $books;
|
||||
|
||||
@@ -143,7 +143,7 @@ class JointPermissionBuilder
|
||||
/**
|
||||
* Rebuild the entity jointPermissions for a collection of entities.
|
||||
*/
|
||||
protected function buildJointPermissionsForEntities(array $entities)
|
||||
protected function buildJointPermissionsForEntities(array $entities): void
|
||||
{
|
||||
$roles = Role::query()->get()->values()->all();
|
||||
$this->deleteManyJointPermissionsForEntities($entities);
|
||||
@@ -155,21 +155,19 @@ class JointPermissionBuilder
|
||||
*
|
||||
* @param Entity[] $entities
|
||||
*/
|
||||
protected function deleteManyJointPermissionsForEntities(array $entities)
|
||||
protected function deleteManyJointPermissionsForEntities(array $entities): void
|
||||
{
|
||||
$simpleEntities = $this->entitiesToSimpleEntities($entities);
|
||||
$idsByType = $this->entitiesToTypeIdMap($simpleEntities);
|
||||
|
||||
DB::transaction(function () use ($idsByType) {
|
||||
foreach ($idsByType as $type => $ids) {
|
||||
foreach (array_chunk($ids, 1000) as $idChunk) {
|
||||
DB::table('joint_permissions')
|
||||
->where('entity_type', '=', $type)
|
||||
->whereIn('entity_id', $idChunk)
|
||||
->delete();
|
||||
}
|
||||
foreach ($idsByType as $type => $ids) {
|
||||
foreach (array_chunk($ids, 1000) as $idChunk) {
|
||||
DB::table('joint_permissions')
|
||||
->where('entity_type', '=', $type)
|
||||
->whereIn('entity_id', $idChunk)
|
||||
->delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +193,7 @@ class JointPermissionBuilder
|
||||
* @param Entity[] $originalEntities
|
||||
* @param Role[] $roles
|
||||
*/
|
||||
protected function createManyJointPermissions(array $originalEntities, array $roles)
|
||||
protected function createManyJointPermissions(array $originalEntities, array $roles): void
|
||||
{
|
||||
$entities = $this->entitiesToSimpleEntities($originalEntities);
|
||||
$jointPermissions = [];
|
||||
@@ -225,11 +223,9 @@ class JointPermissionBuilder
|
||||
}
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($jointPermissions) {
|
||||
foreach (array_chunk($jointPermissions, 1000) as $jointPermissionChunk) {
|
||||
DB::table('joint_permissions')->insert($jointPermissionChunk);
|
||||
}
|
||||
});
|
||||
foreach (array_chunk($jointPermissions, 1000) as $jointPermissionChunk) {
|
||||
DB::table('joint_permissions')->insert($jointPermissionChunk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -7,6 +7,7 @@ use BookStack\Entities\Tools\PermissionsUpdater;
|
||||
use BookStack\Http\Controller;
|
||||
use BookStack\Permissions\Models\EntityPermission;
|
||||
use BookStack\Users\Models\Role;
|
||||
use BookStack\Util\DatabaseTransaction;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PermissionsController extends Controller
|
||||
@@ -40,7 +41,9 @@ class PermissionsController extends Controller
|
||||
$page = $this->queries->pages->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
|
||||
$this->checkOwnablePermission('restrictions-manage', $page);
|
||||
|
||||
$this->permissionsUpdater->updateFromPermissionsForm($page, $request);
|
||||
(new DatabaseTransaction(function () use ($page, $request) {
|
||||
$this->permissionsUpdater->updateFromPermissionsForm($page, $request);
|
||||
}))->run();
|
||||
|
||||
$this->showSuccessNotification(trans('entities.pages_permissions_success'));
|
||||
|
||||
@@ -70,7 +73,9 @@ class PermissionsController extends Controller
|
||||
$chapter = $this->queries->chapters->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
|
||||
$this->checkOwnablePermission('restrictions-manage', $chapter);
|
||||
|
||||
$this->permissionsUpdater->updateFromPermissionsForm($chapter, $request);
|
||||
(new DatabaseTransaction(function () use ($chapter, $request) {
|
||||
$this->permissionsUpdater->updateFromPermissionsForm($chapter, $request);
|
||||
}))->run();
|
||||
|
||||
$this->showSuccessNotification(trans('entities.chapters_permissions_success'));
|
||||
|
||||
@@ -100,7 +105,9 @@ class PermissionsController extends Controller
|
||||
$book = $this->queries->books->findVisibleBySlugOrFail($slug);
|
||||
$this->checkOwnablePermission('restrictions-manage', $book);
|
||||
|
||||
$this->permissionsUpdater->updateFromPermissionsForm($book, $request);
|
||||
(new DatabaseTransaction(function () use ($book, $request) {
|
||||
$this->permissionsUpdater->updateFromPermissionsForm($book, $request);
|
||||
}))->run();
|
||||
|
||||
$this->showSuccessNotification(trans('entities.books_permissions_updated'));
|
||||
|
||||
@@ -130,7 +137,9 @@ class PermissionsController extends Controller
|
||||
$shelf = $this->queries->shelves->findVisibleBySlugOrFail($slug);
|
||||
$this->checkOwnablePermission('restrictions-manage', $shelf);
|
||||
|
||||
$this->permissionsUpdater->updateFromPermissionsForm($shelf, $request);
|
||||
(new DatabaseTransaction(function () use ($shelf, $request) {
|
||||
$this->permissionsUpdater->updateFromPermissionsForm($shelf, $request);
|
||||
}))->run();
|
||||
|
||||
$this->showSuccessNotification(trans('entities.shelves_permissions_updated'));
|
||||
|
||||
@@ -145,7 +154,10 @@ class PermissionsController extends Controller
|
||||
$shelf = $this->queries->shelves->findVisibleBySlugOrFail($slug);
|
||||
$this->checkOwnablePermission('restrictions-manage', $shelf);
|
||||
|
||||
$updateCount = $this->permissionsUpdater->updateBookPermissionsFromShelf($shelf);
|
||||
$updateCount = (new DatabaseTransaction(function () use ($shelf) {
|
||||
return $this->permissionsUpdater->updateBookPermissionsFromShelf($shelf);
|
||||
}))->run();
|
||||
|
||||
$this->showSuccessNotification(trans('entities.shelves_copy_permission_success', ['count' => $updateCount]));
|
||||
|
||||
return redirect($shelf->getUrl());
|
||||
|
@@ -7,6 +7,7 @@ use BookStack\Exceptions\PermissionsException;
|
||||
use BookStack\Facades\Activity;
|
||||
use BookStack\Permissions\Models\RolePermission;
|
||||
use BookStack\Users\Models\Role;
|
||||
use BookStack\Util\DatabaseTransaction;
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
@@ -48,38 +49,42 @@ class PermissionsRepo
|
||||
*/
|
||||
public function saveNewRole(array $roleData): Role
|
||||
{
|
||||
$role = new Role($roleData);
|
||||
$role->mfa_enforced = boolval($roleData['mfa_enforced'] ?? false);
|
||||
$role->save();
|
||||
return (new DatabaseTransaction(function () use ($roleData) {
|
||||
$role = new Role($roleData);
|
||||
$role->mfa_enforced = boolval($roleData['mfa_enforced'] ?? false);
|
||||
$role->save();
|
||||
|
||||
$permissions = $roleData['permissions'] ?? [];
|
||||
$this->assignRolePermissions($role, $permissions);
|
||||
$this->permissionBuilder->rebuildForRole($role);
|
||||
$permissions = $roleData['permissions'] ?? [];
|
||||
$this->assignRolePermissions($role, $permissions);
|
||||
$this->permissionBuilder->rebuildForRole($role);
|
||||
|
||||
Activity::add(ActivityType::ROLE_CREATE, $role);
|
||||
Activity::add(ActivityType::ROLE_CREATE, $role);
|
||||
|
||||
return $role;
|
||||
return $role;
|
||||
}))->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing role.
|
||||
* Ensures Admin system role always have core permissions.
|
||||
* Ensures the Admin system role always has core permissions.
|
||||
*/
|
||||
public function updateRole($roleId, array $roleData): Role
|
||||
{
|
||||
$role = $this->getRoleById($roleId);
|
||||
|
||||
if (isset($roleData['permissions'])) {
|
||||
$this->assignRolePermissions($role, $roleData['permissions']);
|
||||
}
|
||||
return (new DatabaseTransaction(function () use ($role, $roleData) {
|
||||
if (isset($roleData['permissions'])) {
|
||||
$this->assignRolePermissions($role, $roleData['permissions']);
|
||||
}
|
||||
|
||||
$role->fill($roleData);
|
||||
$role->save();
|
||||
$this->permissionBuilder->rebuildForRole($role);
|
||||
$role->fill($roleData);
|
||||
$role->save();
|
||||
$this->permissionBuilder->rebuildForRole($role);
|
||||
|
||||
Activity::add(ActivityType::ROLE_UPDATE, $role);
|
||||
Activity::add(ActivityType::ROLE_UPDATE, $role);
|
||||
|
||||
return $role;
|
||||
return $role;
|
||||
}))->run();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,7 +119,7 @@ class PermissionsRepo
|
||||
/**
|
||||
* Delete a role from the system.
|
||||
* Check it's not an admin role or set as default before deleting.
|
||||
* If a migration Role ID is specified the users assign to the current role
|
||||
* If a migration Role ID is specified, the users assigned to the current role
|
||||
* will be added to the role of the specified id.
|
||||
*
|
||||
* @throws PermissionsException
|
||||
@@ -131,17 +136,19 @@ class PermissionsRepo
|
||||
throw new PermissionsException(trans('errors.role_registration_default_cannot_delete'));
|
||||
}
|
||||
|
||||
if ($migrateRoleId !== 0) {
|
||||
$newRole = Role::query()->find($migrateRoleId);
|
||||
if ($newRole) {
|
||||
$users = $role->users()->pluck('id')->toArray();
|
||||
$newRole->users()->sync($users);
|
||||
(new DatabaseTransaction(function () use ($migrateRoleId, $role) {
|
||||
if ($migrateRoleId !== 0) {
|
||||
$newRole = Role::query()->find($migrateRoleId);
|
||||
if ($newRole) {
|
||||
$users = $role->users()->pluck('id')->toArray();
|
||||
$newRole->users()->sync($users);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$role->entityPermissions()->delete();
|
||||
$role->jointPermissions()->delete();
|
||||
Activity::add(ActivityType::ROLE_DELETE, $role);
|
||||
$role->delete();
|
||||
$role->entityPermissions()->delete();
|
||||
$role->jointPermissions()->delete();
|
||||
Activity::add(ActivityType::ROLE_DELETE, $role);
|
||||
$role->delete();
|
||||
}))->run();
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ use Illuminate\Http\Request;
|
||||
|
||||
class SearchApiController extends ApiController
|
||||
{
|
||||
protected $rules = [
|
||||
protected array $rules = [
|
||||
'all' => [
|
||||
'query' => ['required'],
|
||||
'page' => ['integer', 'min:1'],
|
||||
|
@@ -7,6 +7,7 @@ use BookStack\Entities\Queries\BookQueries;
|
||||
use BookStack\Entities\Tools\BookContents;
|
||||
use BookStack\Facades\Activity;
|
||||
use BookStack\Http\Controller;
|
||||
use BookStack\Util\DatabaseTransaction;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class BookSortController extends Controller
|
||||
@@ -55,16 +56,18 @@ class BookSortController extends Controller
|
||||
|
||||
// Sort via map
|
||||
if ($request->filled('sort-tree')) {
|
||||
$sortMap = BookSortMap::fromJson($request->get('sort-tree'));
|
||||
$booksInvolved = $sorter->sortUsingMap($sortMap);
|
||||
(new DatabaseTransaction(function () use ($book, $request, $sorter, &$loggedActivityForBook) {
|
||||
$sortMap = BookSortMap::fromJson($request->get('sort-tree'));
|
||||
$booksInvolved = $sorter->sortUsingMap($sortMap);
|
||||
|
||||
// Rebuild permissions and add activity for involved books.
|
||||
foreach ($booksInvolved as $bookInvolved) {
|
||||
Activity::add(ActivityType::BOOK_SORT, $bookInvolved);
|
||||
if ($bookInvolved->id === $book->id) {
|
||||
$loggedActivityForBook = true;
|
||||
// Add activity for involved books.
|
||||
foreach ($booksInvolved as $bookInvolved) {
|
||||
Activity::add(ActivityType::BOOK_SORT, $bookInvolved);
|
||||
if ($bookInvolved->id === $book->id) {
|
||||
$loggedActivityForBook = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}))->run();
|
||||
}
|
||||
|
||||
if ($request->filled('auto-sort')) {
|
||||
|
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace BookStack\Sorting;
|
||||
|
||||
use BookStack\App\Model;
|
||||
use BookStack\Entities\Models\Book;
|
||||
use BookStack\Entities\Models\BookChild;
|
||||
use BookStack\Entities\Models\Chapter;
|
||||
|
@@ -16,7 +16,7 @@ class RoleApiController extends ApiController
|
||||
'display_name', 'description', 'mfa_enforced', 'external_auth_id', 'created_at', 'updated_at',
|
||||
];
|
||||
|
||||
protected $rules = [
|
||||
protected array $rules = [
|
||||
'create' => [
|
||||
'display_name' => ['required', 'string', 'min:3', 'max:180'],
|
||||
'description' => ['string', 'max:180'],
|
||||
|
42
app/Util/DatabaseTransaction.php
Normal file
42
app/Util/DatabaseTransaction.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Util;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Run the given code within a database transactions.
|
||||
* Wraps Laravel's own transaction method, but sets a specific runtime isolation method.
|
||||
* This sets a session level since this won't cause issues if already within a transaction,
|
||||
* and this should apply to the next transactions anyway.
|
||||
*
|
||||
* "READ COMMITTED" ensures that changes from other transactions can be read within
|
||||
* a transaction, even if started afterward (and for example, it was blocked by the initial
|
||||
* transaction). This is quite important for things like permission generation, where we would
|
||||
* want to consider the changes made by other committed transactions by the time we come to
|
||||
* regenerate permission access.
|
||||
*
|
||||
* @throws Throwable
|
||||
* @template TReturn of mixed
|
||||
*/
|
||||
class DatabaseTransaction
|
||||
{
|
||||
/**
|
||||
* @param (Closure(static): TReturn) $callback
|
||||
*/
|
||||
public function __construct(
|
||||
protected Closure $callback
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TReturn
|
||||
*/
|
||||
public function run(): mixed
|
||||
{
|
||||
DB::statement('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED');
|
||||
return DB::transaction($this->callback);
|
||||
}
|
||||
}
|
@@ -4,7 +4,6 @@ namespace BookStack\Util;
|
||||
|
||||
use DOMAttr;
|
||||
use DOMElement;
|
||||
use DOMNamedNodeMap;
|
||||
use DOMNode;
|
||||
|
||||
/**
|
||||
@@ -25,6 +24,7 @@ class HtmlDescriptionFilter
|
||||
'ul' => [],
|
||||
'li' => [],
|
||||
'strong' => [],
|
||||
'span' => [],
|
||||
'em' => [],
|
||||
'br' => [],
|
||||
];
|
||||
@@ -59,7 +59,6 @@ class HtmlDescriptionFilter
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var DOMNamedNodeMap $attrs */
|
||||
$attrs = $element->attributes;
|
||||
for ($i = $attrs->length - 1; $i >= 0; $i--) {
|
||||
/** @var DOMAttr $attr */
|
||||
@@ -70,7 +69,8 @@ class HtmlDescriptionFilter
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($element->childNodes as $child) {
|
||||
$childNodes = [...$element->childNodes];
|
||||
foreach ($childNodes as $child) {
|
||||
if ($child instanceof DOMElement) {
|
||||
static::filterElement($child);
|
||||
}
|
||||
|
@@ -38,8 +38,7 @@
|
||||
"socialiteproviders/microsoft-azure": "^5.1",
|
||||
"socialiteproviders/okta": "^4.2",
|
||||
"socialiteproviders/twitch": "^5.3",
|
||||
"ssddanbrown/htmldiff": "^2.0.0",
|
||||
"ssddanbrown/symfony-mailer": "7.2.x-dev"
|
||||
"ssddanbrown/htmldiff": "^2.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.21",
|
||||
|
269
composer.lock
generated
269
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "d9b8455cf3ec02c21bea7ee94463331b",
|
||||
"content-hash": "b7695cb9945ec550970c67da96934daf",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aws/aws-crt-php",
|
||||
@@ -62,16 +62,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.349.2",
|
||||
"version": "3.351.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "63cc727845f077d17cb94791deb327249e1626ce"
|
||||
"reference": "9506d7fdb3cb84f8d7b175c594db9993264814be"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/63cc727845f077d17cb94791deb327249e1626ce",
|
||||
"reference": "63cc727845f077d17cb94791deb327249e1626ce",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9506d7fdb3cb84f8d7b175c594db9993264814be",
|
||||
"reference": "9506d7fdb3cb84f8d7b175c594db9993264814be",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -153,9 +153,9 @@
|
||||
"support": {
|
||||
"forum": "https://github.com/aws/aws-sdk-php/discussions",
|
||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.349.2"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.351.7"
|
||||
},
|
||||
"time": "2025-07-03T18:08:27+00:00"
|
||||
"time": "2025-07-25T18:06:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@@ -1955,16 +1955,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
"version": "v0.3.5",
|
||||
"version": "v0.3.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/prompts.git",
|
||||
"reference": "57b8f7efe40333cdb925700891c7d7465325d3b1"
|
||||
"reference": "86a8b692e8661d0fb308cec64f3d176821323077"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/prompts/zipball/57b8f7efe40333cdb925700891c7d7465325d3b1",
|
||||
"reference": "57b8f7efe40333cdb925700891c7d7465325d3b1",
|
||||
"url": "https://api.github.com/repos/laravel/prompts/zipball/86a8b692e8661d0fb308cec64f3d176821323077",
|
||||
"reference": "86a8b692e8661d0fb308cec64f3d176821323077",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2008,9 +2008,9 @@
|
||||
"description": "Add beautiful and user-friendly forms to your command-line applications.",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/prompts/issues",
|
||||
"source": "https://github.com/laravel/prompts/tree/v0.3.5"
|
||||
"source": "https://github.com/laravel/prompts/tree/v0.3.6"
|
||||
},
|
||||
"time": "2025-02-11T13:34:40+00:00"
|
||||
"time": "2025-07-07T14:17:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
@@ -2075,16 +2075,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/socialite",
|
||||
"version": "v5.21.0",
|
||||
"version": "v5.23.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/socialite.git",
|
||||
"reference": "d83639499ad14985c9a6a9713b70073300ce998d"
|
||||
"reference": "e9e0fc83b9d8d71c8385a5da20e5b95ca6234cf5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/socialite/zipball/d83639499ad14985c9a6a9713b70073300ce998d",
|
||||
"reference": "d83639499ad14985c9a6a9713b70073300ce998d",
|
||||
"url": "https://api.github.com/repos/laravel/socialite/zipball/e9e0fc83b9d8d71c8385a5da20e5b95ca6234cf5",
|
||||
"reference": "e9e0fc83b9d8d71c8385a5da20e5b95ca6234cf5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2143,7 +2143,7 @@
|
||||
"issues": "https://github.com/laravel/socialite/issues",
|
||||
"source": "https://github.com/laravel/socialite"
|
||||
},
|
||||
"time": "2025-05-19T12:56:37+00:00"
|
||||
"time": "2025-07-23T14:16:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/tinker",
|
||||
@@ -2213,16 +2213,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
"version": "2.7.0",
|
||||
"version": "2.7.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/commonmark.git",
|
||||
"reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405"
|
||||
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
|
||||
"reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca",
|
||||
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2251,7 +2251,7 @@
|
||||
"symfony/process": "^5.4 | ^6.0 | ^7.0",
|
||||
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
|
||||
"unleashedtech/php-coding-standard": "^3.1.1",
|
||||
"vimeo/psalm": "^4.24.0 || ^5.0.0"
|
||||
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/yaml": "v2.3+ required if using the Front Matter extension"
|
||||
@@ -2316,7 +2316,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-05-05T12:20:28+00:00"
|
||||
"time": "2025-07-20T12:47:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/config",
|
||||
@@ -3049,16 +3049,16 @@
|
||||
},
|
||||
{
|
||||
"name": "masterminds/html5",
|
||||
"version": "2.9.0",
|
||||
"version": "2.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Masterminds/html5-php.git",
|
||||
"reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6"
|
||||
"reference": "fcf91eb64359852f00d921887b219479b4f21251"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6",
|
||||
"reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6",
|
||||
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251",
|
||||
"reference": "fcf91eb64359852f00d921887b219479b4f21251",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3110,9 +3110,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Masterminds/html5-php/issues",
|
||||
"source": "https://github.com/Masterminds/html5-php/tree/2.9.0"
|
||||
"source": "https://github.com/Masterminds/html5-php/tree/2.10.0"
|
||||
},
|
||||
"time": "2024-03-31T07:05:07+00:00"
|
||||
"time": "2025-07-25T09:04:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
@@ -4894,16 +4894,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sabberworm/php-css-parser",
|
||||
"version": "v8.8.0",
|
||||
"version": "v8.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MyIntervals/PHP-CSS-Parser.git",
|
||||
"reference": "3de493bdddfd1f051249af725c7e0d2c38fed740"
|
||||
"reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/3de493bdddfd1f051249af725c7e0d2c38fed740",
|
||||
"reference": "3de493bdddfd1f051249af725c7e0d2c38fed740",
|
||||
"url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d8e916507b88e389e26d4ab03c904a082aa66bb9",
|
||||
"reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4911,7 +4911,8 @@
|
||||
"php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41"
|
||||
"phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41",
|
||||
"rawr/cross-data-providers": "^2.0.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "for parsing UTF-8 CSS"
|
||||
@@ -4953,9 +4954,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues",
|
||||
"source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.8.0"
|
||||
"source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.9.0"
|
||||
},
|
||||
"time": "2025-03-23T17:59:05+00:00"
|
||||
"time": "2025-07-11T13:20:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "socialiteproviders/discord",
|
||||
@@ -5325,80 +5326,6 @@
|
||||
],
|
||||
"time": "2025-07-07T11:55:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ssddanbrown/symfony-mailer",
|
||||
"version": "7.2.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ssddanbrown/symfony-mailer.git",
|
||||
"reference": "e9de8dccd76a63fc23475016e6574da6f5f12a2d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ssddanbrown/symfony-mailer/zipball/e9de8dccd76a63fc23475016e6574da6f5f12a2d",
|
||||
"reference": "e9de8dccd76a63fc23475016e6574da6f5f12a2d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"egulias/email-validator": "^2.1.10|^3|^4",
|
||||
"php": ">=8.2",
|
||||
"psr/event-dispatcher": "^1",
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/event-dispatcher": "^6.4|^7.0",
|
||||
"symfony/mime": "^7.2",
|
||||
"symfony/service-contracts": "^2.5|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/http-client-contracts": "<2.5",
|
||||
"symfony/http-kernel": "<6.4",
|
||||
"symfony/messenger": "<6.4",
|
||||
"symfony/mime": "<6.4",
|
||||
"symfony/twig-bridge": "<6.4"
|
||||
},
|
||||
"replace": {
|
||||
"symfony/mailer": "^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^6.4|^7.0",
|
||||
"symfony/http-client": "^6.4|^7.0",
|
||||
"symfony/messenger": "^6.4|^7.0",
|
||||
"symfony/twig-bridge": "^6.4|^7.0"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Mailer\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dan Brown",
|
||||
"homepage": "https://danb.me"
|
||||
},
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Helps sending emails",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/ssddanbrown/symfony-mailer/tree/7.2"
|
||||
},
|
||||
"time": "2025-01-11T14:57:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/clock",
|
||||
"version": "v7.3.0",
|
||||
@@ -6189,6 +6116,86 @@
|
||||
],
|
||||
"time": "2025-06-28T08:24:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mailer",
|
||||
"version": "v7.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mailer.git",
|
||||
"reference": "b5db5105b290bdbea5ab27b89c69effcf1cb3368"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mailer/zipball/b5db5105b290bdbea5ab27b89c69effcf1cb3368",
|
||||
"reference": "b5db5105b290bdbea5ab27b89c69effcf1cb3368",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"egulias/email-validator": "^2.1.10|^3|^4",
|
||||
"php": ">=8.2",
|
||||
"psr/event-dispatcher": "^1",
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/event-dispatcher": "^6.4|^7.0",
|
||||
"symfony/mime": "^7.2",
|
||||
"symfony/service-contracts": "^2.5|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/http-client-contracts": "<2.5",
|
||||
"symfony/http-kernel": "<6.4",
|
||||
"symfony/messenger": "<6.4",
|
||||
"symfony/mime": "<6.4",
|
||||
"symfony/twig-bridge": "<6.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^6.4|^7.0",
|
||||
"symfony/http-client": "^6.4|^7.0",
|
||||
"symfony/messenger": "^6.4|^7.0",
|
||||
"symfony/twig-bridge": "^6.4|^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Mailer\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Helps sending emails",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mailer/tree/v7.3.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-06-27T19:55:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v7.3.0",
|
||||
@@ -8131,16 +8138,16 @@
|
||||
},
|
||||
{
|
||||
"name": "larastan/larastan",
|
||||
"version": "v3.5.0",
|
||||
"version": "v3.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/larastan/larastan.git",
|
||||
"reference": "e8ccd73008487ba91da9877b373f8c447743f1ce"
|
||||
"reference": "6431d010dd383a9279eb8874a76ddb571738564a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/larastan/larastan/zipball/e8ccd73008487ba91da9877b373f8c447743f1ce",
|
||||
"reference": "e8ccd73008487ba91da9877b373f8c447743f1ce",
|
||||
"url": "https://api.github.com/repos/larastan/larastan/zipball/6431d010dd383a9279eb8874a76ddb571738564a",
|
||||
"reference": "6431d010dd383a9279eb8874a76ddb571738564a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -8208,7 +8215,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/larastan/larastan/issues",
|
||||
"source": "https://github.com/larastan/larastan/tree/v3.5.0"
|
||||
"source": "https://github.com/larastan/larastan/tree/v3.6.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -8216,7 +8223,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-06-19T22:41:50+00:00"
|
||||
"time": "2025-07-11T06:52:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
@@ -8580,16 +8587,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.17",
|
||||
"version": "2.1.20",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "89b5ef665716fa2a52ecd2633f21007a6a349053"
|
||||
"reference": "a9ccfef95210f92ba6feea6e8d1eef42b5605499"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053",
|
||||
"reference": "89b5ef665716fa2a52ecd2633f21007a6a349053",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/a9ccfef95210f92ba6feea6e8d1eef42b5605499",
|
||||
"reference": "a9ccfef95210f92ba6feea6e8d1eef42b5605499",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -8634,7 +8641,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-05-21T20:55:28+00:00"
|
||||
"time": "2025-07-26T20:45:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
@@ -8973,16 +8980,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "11.5.26",
|
||||
"version": "11.5.27",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "4ad8fe263a0b55b54a8028c38a18e3c5bef312e0"
|
||||
"reference": "446d43867314781df7e9adf79c3ec7464956fd8f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4ad8fe263a0b55b54a8028c38a18e3c5bef312e0",
|
||||
"reference": "4ad8fe263a0b55b54a8028c38a18e3c5bef312e0",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/446d43867314781df7e9adf79c3ec7464956fd8f",
|
||||
"reference": "446d43867314781df7e9adf79c3ec7464956fd8f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -8992,7 +8999,7 @@
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"myclabs/deep-copy": "^1.13.1",
|
||||
"myclabs/deep-copy": "^1.13.3",
|
||||
"phar-io/manifest": "^2.0.4",
|
||||
"phar-io/version": "^3.2.1",
|
||||
"php": ">=8.2",
|
||||
@@ -9054,7 +9061,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.26"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.27"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -9078,7 +9085,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-07-04T05:58:21+00:00"
|
||||
"time": "2025-07-11T04:10:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
@@ -10318,9 +10325,7 @@
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"ssddanbrown/symfony-mailer": 20
|
||||
},
|
||||
"stability-flags": {},
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
@@ -24,6 +24,7 @@ class ImportFactory extends Factory
|
||||
'path' => 'uploads/files/imports/' . Str::random(10) . '.zip',
|
||||
'name' => $this->faker->words(3, true),
|
||||
'type' => 'book',
|
||||
'size' => rand(1, 1001),
|
||||
'metadata' => '{"name": "My book"}',
|
||||
'created_at' => User::factory(),
|
||||
];
|
||||
|
4
dev/api/requests/imports-run.json
Normal file
4
dev/api/requests/imports-run.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"parent_type": "book",
|
||||
"parent_id": 28
|
||||
}
|
10
dev/api/responses/imports-create.json
Normal file
10
dev/api/responses/imports-create.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"type": "chapter",
|
||||
"name": "Pension Providers",
|
||||
"created_by": 1,
|
||||
"size": 2757,
|
||||
"path": "uploads\/files\/imports\/ghnxmS3u9QxLWu82.zip",
|
||||
"updated_at": "2025-07-18T14:50:27.000000Z",
|
||||
"created_at": "2025-07-18T14:50:27.000000Z",
|
||||
"id": 31
|
||||
}
|
23
dev/api/responses/imports-list.json
Normal file
23
dev/api/responses/imports-list.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": 25,
|
||||
"name": "IT Department",
|
||||
"size": 618462,
|
||||
"type": "book",
|
||||
"created_by": 1,
|
||||
"created_at": "2024-12-20T18:40:38.000000Z",
|
||||
"updated_at": "2024-12-20T18:40:38.000000Z"
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"name": "Clients",
|
||||
"size": 15364,
|
||||
"type": "chapter",
|
||||
"created_by": 1,
|
||||
"created_at": "2025-03-20T12:41:44.000000Z",
|
||||
"updated_at": "2025-03-20T12:41:44.000000Z"
|
||||
}
|
||||
],
|
||||
"total": 2
|
||||
}
|
51
dev/api/responses/imports-read.json
Normal file
51
dev/api/responses/imports-read.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"id": 25,
|
||||
"name": "IT Department",
|
||||
"path": "uploads\/files\/imports\/7YOpZ6sGIEbYdRFL.zip",
|
||||
"size": 618462,
|
||||
"type": "book",
|
||||
"created_by": 1,
|
||||
"created_at": "2024-12-20T18:40:38.000000Z",
|
||||
"updated_at": "2024-12-20T18:40:38.000000Z",
|
||||
"details": {
|
||||
"id": 4,
|
||||
"name": "IT Department",
|
||||
"chapters": [
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Server Systems",
|
||||
"priority": 1,
|
||||
"pages": [
|
||||
{
|
||||
"id": 22,
|
||||
"name": "prod-aws-stonehawk",
|
||||
"priority": 0,
|
||||
"attachments": [],
|
||||
"images": [],
|
||||
"tags": []
|
||||
}
|
||||
],
|
||||
"tags": []
|
||||
}
|
||||
],
|
||||
"pages": [
|
||||
{
|
||||
"id": 23,
|
||||
"name": "Member Onboarding Guide",
|
||||
"priority": 0,
|
||||
"attachments": [],
|
||||
"images": [],
|
||||
"tags": []
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"name": "IT Holiday Party Event",
|
||||
"priority": 2,
|
||||
"attachments": [],
|
||||
"images": [],
|
||||
"tags": []
|
||||
}
|
||||
],
|
||||
"tags": []
|
||||
}
|
||||
}
|
14
dev/api/responses/imports-run.json
Normal file
14
dev/api/responses/imports-run.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": 1067,
|
||||
"book_id": 28,
|
||||
"slug": "pension-providers",
|
||||
"name": "Pension Providers",
|
||||
"description": "Details on the various pension providers that are available",
|
||||
"priority": 7,
|
||||
"created_at": "2025-07-18T14:53:35.000000Z",
|
||||
"updated_at": "2025-07-18T14:53:36.000000Z",
|
||||
"created_by": 1,
|
||||
"updated_by": 1,
|
||||
"owned_by": 1,
|
||||
"default_template_id": null
|
||||
}
|
@@ -13,7 +13,7 @@ const entryPoints = {
|
||||
app: path.join(__dirname, '../../resources/js/app.ts'),
|
||||
code: path.join(__dirname, '../../resources/js/code/index.mjs'),
|
||||
'legacy-modes': path.join(__dirname, '../../resources/js/code/legacy-modes.mjs'),
|
||||
markdown: path.join(__dirname, '../../resources/js/markdown/index.mjs'),
|
||||
markdown: path.join(__dirname, '../../resources/js/markdown/index.mts'),
|
||||
wysiwyg: path.join(__dirname, '../../resources/js/wysiwyg/index.ts'),
|
||||
};
|
||||
|
||||
|
@@ -345,7 +345,7 @@ Link: tj/co
|
||||
codemirror
|
||||
License: MIT
|
||||
License File: node_modules/codemirror/LICENSE
|
||||
Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <*******@*****.***> and others
|
||||
Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others
|
||||
Source: https://github.com/codemirror/basic-setup.git
|
||||
Link: https://github.com/codemirror/basic-setup.git
|
||||
-----------
|
||||
@@ -711,13 +711,13 @@ eslint-scope
|
||||
License: BSD-2-Clause
|
||||
License File: node_modules/eslint-scope/LICENSE
|
||||
Copyright: Copyright (C) 2012-2013 Yusuke Suzuki (twitter: @Constellation) and other contributors.
|
||||
Source: eslint/js
|
||||
Source: https://github.com/eslint/js.git
|
||||
Link: https://github.com/eslint/js/blob/main/packages/eslint-scope/README.md
|
||||
-----------
|
||||
eslint-visitor-keys
|
||||
License: Apache-2.0
|
||||
License File: node_modules/eslint-visitor-keys/LICENSE
|
||||
Source: eslint/js
|
||||
Source: https://github.com/eslint/js.git
|
||||
Link: https://github.com/eslint/js/blob/main/packages/eslint-visitor-keys/README.md
|
||||
-----------
|
||||
eslint
|
||||
@@ -731,7 +731,7 @@ License: BSD-2-Clause
|
||||
License File: node_modules/espree/LICENSE
|
||||
Copyright: Copyright (c) Open JS Foundation
|
||||
All rights reserved.
|
||||
Source: eslint/js
|
||||
Source: https://github.com/eslint/js.git
|
||||
Link: https://github.com/eslint/js/blob/main/packages/espree/README.md
|
||||
-----------
|
||||
esprima
|
||||
@@ -1252,6 +1252,13 @@ Copyright: Copyright (c) 2019 Inspect JS
|
||||
Source: git+https://github.com/inspect-js/is-map.git
|
||||
Link: https://github.com/inspect-js/is-map#readme
|
||||
-----------
|
||||
is-negative-zero
|
||||
License: MIT
|
||||
License File: node_modules/is-negative-zero/LICENSE
|
||||
Copyright: Copyright (c) 2014 Jordan Harband
|
||||
Source: git://github.com/inspect-js/is-negative-zero.git
|
||||
Link: https://github.com/inspect-js/is-negative-zero
|
||||
-----------
|
||||
is-number-object
|
||||
License: MIT
|
||||
License File: node_modules/is-number-object/LICENSE
|
||||
@@ -2493,6 +2500,13 @@ Copyright: Copyright (c) 2016-2022 Isaac Z. Schlueter <*@***.**>, James Talmage
|
||||
Source: tapjs/stack-utils
|
||||
Link: tapjs/stack-utils
|
||||
-----------
|
||||
stop-iteration-iterator
|
||||
License: MIT
|
||||
License File: node_modules/stop-iteration-iterator/LICENSE
|
||||
Copyright: Copyright (c) 2023 Jordan Harband
|
||||
Source: git+https://github.com/ljharb/stop-iteration-iterator.git
|
||||
Link: https://github.com/ljharb/stop-iteration-iterator#readme
|
||||
-----------
|
||||
string-length
|
||||
License: MIT
|
||||
License File: node_modules/string-length/license
|
||||
@@ -2992,6 +3006,13 @@ Copyright: Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||
Source: https://github.com/babel/babel.git
|
||||
Link: https://github.com/babel/babel.git
|
||||
-----------
|
||||
@babel/helper-globals
|
||||
License: MIT
|
||||
License File: node_modules/@babel/helper-globals/LICENSE
|
||||
Copyright: Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||
Source: https://github.com/babel/babel.git
|
||||
Link: https://github.com/babel/babel.git
|
||||
-----------
|
||||
@babel/helper-module-imports
|
||||
License: MIT
|
||||
License File: node_modules/@babel/helper-module-imports/LICENSE
|
||||
@@ -3038,7 +3059,7 @@ Link: https://github.com/babel/babel.git
|
||||
License: MIT
|
||||
License File: node_modules/@babel/helpers/LICENSE
|
||||
Copyright: Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||
Copyright (c) 2014-present, Facebook, Inc. (ONLY ./src/helpers/regeneratorRuntime.js)
|
||||
Copyright (c) 2014-present, Facebook, Inc. (ONLY ./src/helpers/regenerator* files)
|
||||
Source: https://github.com/babel/babel.git
|
||||
Link: https://babel.dev/docs/en/next/babel-helpers
|
||||
-----------
|
||||
@@ -3233,7 +3254,7 @@ Link: https://github.com/codemirror/lang-javascript.git
|
||||
@codemirror/lang-json
|
||||
License: MIT
|
||||
License File: node_modules/@codemirror/lang-json/LICENSE
|
||||
Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <*******@*****.***> and others
|
||||
Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others
|
||||
Source: https://github.com/codemirror/lang-json.git
|
||||
Link: https://github.com/codemirror/lang-json.git
|
||||
-----------
|
||||
@@ -3247,7 +3268,7 @@ Link: https://github.com/codemirror/lang-markdown.git
|
||||
@codemirror/lang-php
|
||||
License: MIT
|
||||
License File: node_modules/@codemirror/lang-php/LICENSE
|
||||
Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <*******@*****.***> and others
|
||||
Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others
|
||||
Source: https://github.com/codemirror/lang-php.git
|
||||
Link: https://github.com/codemirror/lang-php.git
|
||||
-----------
|
||||
@@ -3337,7 +3358,7 @@ Link: https://github.com/eslint-community/regexpp#readme
|
||||
License: Apache-2.0
|
||||
License File: node_modules/@eslint/config-array/LICENSE
|
||||
Source: git+https://github.com/eslint/rewrite.git
|
||||
Link: https://github.com/eslint/rewrite#readme
|
||||
Link: https://github.com/eslint/rewrite/tree/main/packages/config-array#readme
|
||||
-----------
|
||||
@eslint/config-helpers
|
||||
License: Apache-2.0
|
||||
@@ -3349,7 +3370,7 @@ Link: https://github.com/eslint/rewrite/tree/main/packages/config-helpers#readme
|
||||
License: Apache-2.0
|
||||
License File: node_modules/@eslint/core/LICENSE
|
||||
Source: git+https://github.com/eslint/rewrite.git
|
||||
Link: https://github.com/eslint/rewrite#readme
|
||||
Link: https://github.com/eslint/rewrite/tree/main/packages/core#readme
|
||||
-----------
|
||||
@eslint/eslintrc
|
||||
License: MIT
|
||||
@@ -3373,7 +3394,7 @@ Link: https://github.com/eslint/rewrite#readme
|
||||
License: Apache-2.0
|
||||
License File: node_modules/@eslint/plugin-kit/LICENSE
|
||||
Source: git+https://github.com/eslint/rewrite.git
|
||||
Link: https://github.com/eslint/rewrite#readme
|
||||
Link: https://github.com/eslint/rewrite/tree/main/packages/plugin-kit#readme
|
||||
-----------
|
||||
@humanfs/core
|
||||
License: Apache-2.0
|
||||
@@ -3514,9 +3535,9 @@ Link: https://github.com/jestjs/jest.git
|
||||
@jridgewell/gen-mapping
|
||||
License: MIT
|
||||
License File: node_modules/@jridgewell/gen-mapping/LICENSE
|
||||
Copyright: Copyright 2022 Justin Ridgewell <**********@******.***>
|
||||
Source: https://github.com/jridgewell/gen-mapping
|
||||
Link: https://github.com/jridgewell/gen-mapping
|
||||
Copyright: Copyright 2024 Justin Ridgewell <******@*********.****>
|
||||
Source: git+https://github.com/jridgewell/sourcemaps.git
|
||||
Link: https://github.com/jridgewell/sourcemaps/tree/main/packages/gen-mapping
|
||||
-----------
|
||||
@jridgewell/resolve-uri
|
||||
License: MIT
|
||||
@@ -3525,26 +3546,19 @@ Copyright: Copyright 2019 Justin Ridgewell <**********@******.***>
|
||||
Source: https://github.com/jridgewell/resolve-uri
|
||||
Link: https://github.com/jridgewell/resolve-uri
|
||||
-----------
|
||||
@jridgewell/set-array
|
||||
License: MIT
|
||||
License File: node_modules/@jridgewell/set-array/LICENSE
|
||||
Copyright: Copyright 2022 Justin Ridgewell <**********@******.***>
|
||||
Source: https://github.com/jridgewell/set-array
|
||||
Link: https://github.com/jridgewell/set-array
|
||||
-----------
|
||||
@jridgewell/sourcemap-codec
|
||||
License: MIT
|
||||
License File: node_modules/@jridgewell/sourcemap-codec/LICENSE
|
||||
Copyright: Copyright (c) 2015 Rich Harris
|
||||
Source: git+https://github.com/jridgewell/sourcemap-codec.git
|
||||
Link: git+https://github.com/jridgewell/sourcemap-codec.git
|
||||
Copyright: Copyright 2024 Justin Ridgewell <******@*********.****>
|
||||
Source: git+https://github.com/jridgewell/sourcemaps.git
|
||||
Link: https://github.com/jridgewell/sourcemaps/tree/main/packages/sourcemap-codec
|
||||
-----------
|
||||
@jridgewell/trace-mapping
|
||||
License: MIT
|
||||
License File: node_modules/@jridgewell/trace-mapping/LICENSE
|
||||
Copyright: Copyright 2022 Justin Ridgewell <******@*********.****>
|
||||
Source: git+https://github.com/jridgewell/trace-mapping.git
|
||||
Link: git+https://github.com/jridgewell/trace-mapping.git
|
||||
Copyright: Copyright 2024 Justin Ridgewell <******@*********.****>
|
||||
Source: git+https://github.com/jridgewell/sourcemaps.git
|
||||
Link: https://github.com/jridgewell/sourcemaps/tree/main/packages/trace-mapping
|
||||
-----------
|
||||
@lezer/common
|
||||
License: MIT
|
||||
@@ -3813,6 +3827,27 @@ License: MIT
|
||||
Source: https://www.github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
Link: https://www.github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
-----------
|
||||
@types/linkify-it
|
||||
License: MIT
|
||||
License File: node_modules/@types/linkify-it/LICENSE
|
||||
Copyright: Copyright (c) Microsoft Corporation.
|
||||
Source: https://github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
Link: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/linkify-it
|
||||
-----------
|
||||
@types/markdown-it
|
||||
License: MIT
|
||||
License File: node_modules/@types/markdown-it/LICENSE
|
||||
Copyright: Copyright (c) Microsoft Corporation.
|
||||
Source: https://github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
Link: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/markdown-it
|
||||
-----------
|
||||
@types/mdurl
|
||||
License: MIT
|
||||
License File: node_modules/@types/mdurl/LICENSE
|
||||
Copyright: Copyright (c) Microsoft Corporation.
|
||||
Source: https://github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
Link: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/mdurl
|
||||
-----------
|
||||
@types/node
|
||||
License: MIT
|
||||
License File: node_modules/@types/node/LICENSE
|
||||
|
@@ -543,13 +543,6 @@ Copyright: Copyright (c) 2024 Nathan Herald, Rohland de Charmoy, Dan Brown
|
||||
Source: https://codeberg.org/danb/HtmlDiff
|
||||
Link: https://codeberg.org/danb/HtmlDiff
|
||||
-----------
|
||||
ssddanbrown/symfony-mailer
|
||||
License: MIT
|
||||
License File: vendor/ssddanbrown/symfony-mailer/LICENSE
|
||||
Copyright: Copyright (c) 2019-present Fabien Potencier
|
||||
Source: https://github.com/ssddanbrown/symfony-mailer.git
|
||||
Link: https://symfony.com
|
||||
-----------
|
||||
symfony/clock
|
||||
License: MIT
|
||||
License File: vendor/symfony/clock/LICENSE
|
||||
@@ -620,6 +613,13 @@ Copyright: Copyright (c) 2004-present Fabien Potencier
|
||||
Source: https://github.com/symfony/http-kernel.git
|
||||
Link: https://symfony.com
|
||||
-----------
|
||||
symfony/mailer
|
||||
License: MIT
|
||||
License File: vendor/symfony/mailer/LICENSE
|
||||
Copyright: Copyright (c) 2019-present Fabien Potencier
|
||||
Source: https://github.com/symfony/mailer.git
|
||||
Link: https://symfony.com
|
||||
-----------
|
||||
symfony/mime
|
||||
License: MIT
|
||||
License File: vendor/symfony/mime/LICENSE
|
||||
|
@@ -30,8 +30,8 @@ return [
|
||||
'create' => 'إنشاء',
|
||||
'update' => 'تحديث',
|
||||
'edit' => 'تعديل',
|
||||
'archive' => 'Archive',
|
||||
'unarchive' => 'Un-Archive',
|
||||
'archive' => 'أرشف',
|
||||
'unarchive' => 'إلغاء الأرشفة',
|
||||
'sort' => 'سرد',
|
||||
'move' => 'نقل',
|
||||
'copy' => 'نسخ',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'نص مرتفع',
|
||||
'subscript' => 'نص منخفض',
|
||||
'text_color' => 'لون النص',
|
||||
'highlight_color' => 'لون التمييز',
|
||||
'custom_color' => 'لون مخصص',
|
||||
'remove_color' => 'إزالة اللون',
|
||||
'background_color' => 'لون الخلفية',
|
||||
|
@@ -248,7 +248,7 @@ return [
|
||||
'pages_edit_switch_to_markdown_stable' => '(محتوى مستقر)',
|
||||
'pages_edit_switch_to_wysiwyg' => 'التبديل إلى محرر ما تراه هو ما تحصل عليه -WYSIWYG-',
|
||||
'pages_edit_switch_to_new_wysiwyg' => 'التبديل إلى محرر ما تراه هو ما تحصل عليه الجديد -new WYSIWYG-',
|
||||
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)',
|
||||
'pages_edit_switch_to_new_wysiwyg_desc' => '(في الاختبار التجريبي)',
|
||||
'pages_edit_set_changelog' => 'تثبيت سجل التعديل',
|
||||
'pages_edit_enter_changelog_desc' => 'ضع وصف مختصر للتعديلات التي تمت',
|
||||
'pages_edit_enter_changelog' => 'أدخل سجل التعديل',
|
||||
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'إدخال رسمة',
|
||||
'pages_md_show_preview' => 'عرض المعاينة',
|
||||
'pages_md_sync_scroll' => 'مزامنة معاينة التمرير',
|
||||
'pages_md_plain_editor' => 'محرر النصوص العادي',
|
||||
'pages_drawing_unsaved' => 'تم العثور على رسم غير محفوظ',
|
||||
'pages_drawing_unsaved_confirm' => 'تم العثور على بيانات رسم غير محفوظة من محاولة حفظ رسم سابقة فاشلة. هل ترغب في استعادة هذا الرسم غير المحفوظ ومواصلة تحريره؟',
|
||||
'pages_not_in_chapter' => 'صفحة ليست في فصل',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Горен индекс',
|
||||
'subscript' => 'Долен индекс',
|
||||
'text_color' => 'Цвят на текста',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Цвят по избор',
|
||||
'remove_color' => 'Премахване на цвят',
|
||||
'background_color' => 'Фонов цвят',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Вмъкни рисунка',
|
||||
'pages_md_show_preview' => 'Show preview',
|
||||
'pages_md_sync_scroll' => 'Sync preview scroll',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Unsaved Drawing Found',
|
||||
'pages_drawing_unsaved_confirm' => 'Unsaved drawing data was found from a previous failed drawing save attempt. Would you like to restore and continue editing this unsaved drawing?',
|
||||
'pages_not_in_chapter' => 'Страницата не принадлежи в никоя глава',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Superscript',
|
||||
'subscript' => 'Subscript',
|
||||
'text_color' => 'Text color',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Custom color',
|
||||
'remove_color' => 'Remove color',
|
||||
'background_color' => 'Background color',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Insert Drawing',
|
||||
'pages_md_show_preview' => 'Show preview',
|
||||
'pages_md_sync_scroll' => 'Sync preview scroll',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Unsaved Drawing Found',
|
||||
'pages_drawing_unsaved_confirm' => 'Unsaved drawing data was found from a previous failed drawing save attempt. Would you like to restore and continue editing this unsaved drawing?',
|
||||
'pages_not_in_chapter' => 'Page is not in a chapter',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Superscript',
|
||||
'subscript' => 'Subscript',
|
||||
'text_color' => 'Text color',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Custom color',
|
||||
'remove_color' => 'Remove color',
|
||||
'background_color' => 'Background color',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Insert Drawing',
|
||||
'pages_md_show_preview' => 'Show preview',
|
||||
'pages_md_sync_scroll' => 'Sync preview scroll',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Unsaved Drawing Found',
|
||||
'pages_drawing_unsaved_confirm' => 'Unsaved drawing data was found from a previous failed drawing save attempt. Would you like to restore and continue editing this unsaved drawing?',
|
||||
'pages_not_in_chapter' => 'Page is not in a chapter',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Superíndex',
|
||||
'subscript' => 'Subíndex',
|
||||
'text_color' => 'Color del text',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Color personalitzat',
|
||||
'remove_color' => 'Elimina el color',
|
||||
'background_color' => 'Color de fons',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Insereix un dibuix',
|
||||
'pages_md_show_preview' => 'Mostra la visualització prèvia',
|
||||
'pages_md_sync_scroll' => 'Sincronitza el desplaçament de la visualització prèvia',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'S’ha trobat un dibuix sense desar',
|
||||
'pages_drawing_unsaved_confirm' => 'S’han trobat dades d’un dibuix d’un intent anterior de desar un dibuix. Voleu restaurar aquest dibuix no desat per a reprendre’n l’edició?',
|
||||
'pages_not_in_chapter' => 'La pàgina no és un capítol',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'horní index',
|
||||
'subscript' => 'Dolní index',
|
||||
'text_color' => 'Barva textu:',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Vlastní barva',
|
||||
'remove_color' => 'Odstranit barvu',
|
||||
'background_color' => 'Barva pozadí',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Vložit kresbu',
|
||||
'pages_md_show_preview' => 'Zobrazit náhled',
|
||||
'pages_md_sync_scroll' => 'Synchronizovat náhled',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Nalezen neuložený výkres',
|
||||
'pages_drawing_unsaved_confirm' => 'Byly nalezeny neuložené kresby z předchozí neúspěšné pokusu o uložení kresby. Chcete je obnovit a pokračovat v úpravě této neuložené kresby?',
|
||||
'pages_not_in_chapter' => 'Stránka není v kapitole',
|
||||
@@ -395,7 +396,7 @@ return [
|
||||
'comment_none' => 'Žádné komentáře k zobrazení',
|
||||
'comment_placeholder' => 'Zde zadejte komentář',
|
||||
'comment_thread_count' => '{0}:count vláken komentářů|{1}:count vlákno komentářů|[2,4]:count vlákna komentářů|[5,*]:count vláken komentářů',
|
||||
'comment_archived_count' => ':count archivováno',
|
||||
'comment_archived_count' => '[0,1]:count archivováno|[2,4]:count archivována|[5,*]:count archivováno',
|
||||
'comment_archived_threads' => 'Archivovaná vlákna',
|
||||
'comment_save' => 'Uložit komentář',
|
||||
'comment_new' => 'Nový komentář',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Uwchysgrif',
|
||||
'subscript' => 'Isysgrif',
|
||||
'text_color' => 'Lliw testun',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Lliw addasu',
|
||||
'remove_color' => 'Dileu lliw',
|
||||
'background_color' => 'Lliw cefnder',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Mewnosod Llun',
|
||||
'pages_md_show_preview' => 'Dangos rhagolwg',
|
||||
'pages_md_sync_scroll' => 'Cydamseru sgrôl ragolwg',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Canfuwyd Llun heb ei Gadw',
|
||||
'pages_drawing_unsaved_confirm' => 'Canfuwyd data llun heb ei gadw o ymgais aflwyddiannus blaenorol i gadw llun. Hoffech chi adfer a pharhau i olygu\'r llun heb ei gadw?',
|
||||
'pages_not_in_chapter' => 'Nid yw\'r dudalen mewn pennod',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Hævet',
|
||||
'subscript' => 'Sænket',
|
||||
'text_color' => 'Tekstfarve',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Tilpasset farve',
|
||||
'remove_color' => 'Fjern farve',
|
||||
'background_color' => 'Baggrundsfarve',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Indsæt tegning',
|
||||
'pages_md_show_preview' => 'Vis forhåndsvisning',
|
||||
'pages_md_sync_scroll' => 'Rulning af forhåndsvisning af synkronisering',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Ikke gemt tegning fundet',
|
||||
'pages_drawing_unsaved_confirm' => 'Der blev fundet ikke-gemte tegningsdata fra et tidligere mislykket forsøg på at gemme en tegning. Vil du gendanne og fortsætte med at redigere denne ikke-gemte tegning?',
|
||||
'pages_not_in_chapter' => 'Side er ikke i et kapitel',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Hochgestellt',
|
||||
'subscript' => 'Tiefgestellt',
|
||||
'text_color' => 'Schriftfarbe',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Benutzerdefinierte Farbe',
|
||||
'remove_color' => 'Farbe entfernen',
|
||||
'background_color' => 'Hintergrundfarbe',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Zeichnung einfügen',
|
||||
'pages_md_show_preview' => 'Vorschau anzeigen',
|
||||
'pages_md_sync_scroll' => 'Vorschau synchronisieren',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Ungespeicherte Zeichnung gefunden',
|
||||
'pages_drawing_unsaved_confirm' => 'Es wurden ungespeicherte Zeichnungsdaten von einem früheren, fehlgeschlagenen Versuch, die Zeichnung zu speichern, gefunden. Möchten Sie diese ungespeicherte Zeichnung wiederherstellen und weiter bearbeiten?',
|
||||
'pages_not_in_chapter' => 'Seite ist in keinem Kapitel',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Hochgestellt',
|
||||
'subscript' => 'Tiefgestellt',
|
||||
'text_color' => 'Textfarbe',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Benutzerdefinierte Farbe',
|
||||
'remove_color' => 'Farbe entfernen',
|
||||
'background_color' => 'Hintergrundfarbe',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Zeichnung einfügen',
|
||||
'pages_md_show_preview' => 'Vorschau anzeigen',
|
||||
'pages_md_sync_scroll' => 'Vorschau synchronisieren',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Ungespeicherte Zeichnung gefunden',
|
||||
'pages_drawing_unsaved_confirm' => 'Es wurden ungespeicherte Zeichnungsdaten von einem früheren, fehlgeschlagenen Versuch, die Zeichnung zu speichern, gefunden. Möchtest du diese ungespeicherte Zeichnung wiederherstellen und weiter bearbeiten?',
|
||||
'pages_not_in_chapter' => 'Seite ist in keinem Kapitel',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Εκθέτης',
|
||||
'subscript' => 'Δείκτης',
|
||||
'text_color' => 'Χρώμα κειμένου',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Προσαρμογή χρώματος',
|
||||
'remove_color' => 'Αφαίρεση χρώματος',
|
||||
'background_color' => 'Χρώμα φόντου',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Εισαγωγή Σχεδίου',
|
||||
'pages_md_show_preview' => 'Εμφάνιση προεπισκόπησης',
|
||||
'pages_md_sync_scroll' => 'Συγχρονισμός προεπισκόπησης',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Unsaved Drawing Found',
|
||||
'pages_drawing_unsaved_confirm' => 'Unsaved drawing data was found from a previous failed drawing save attempt. Would you like to restore and continue editing this unsaved drawing?',
|
||||
'pages_not_in_chapter' => 'Η σελίδα δεν είναι σε κεφάλαιο',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Superscript',
|
||||
'subscript' => 'Subscript',
|
||||
'text_color' => 'Text color',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Custom color',
|
||||
'remove_color' => 'Remove color',
|
||||
'background_color' => 'Background color',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Insert Drawing',
|
||||
'pages_md_show_preview' => 'Show preview',
|
||||
'pages_md_sync_scroll' => 'Sync preview scroll',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Unsaved Drawing Found',
|
||||
'pages_drawing_unsaved_confirm' => 'Unsaved drawing data was found from a previous failed drawing save attempt. Would you like to restore and continue editing this unsaved drawing?',
|
||||
'pages_not_in_chapter' => 'Page is not in a chapter',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Superíndice',
|
||||
'subscript' => 'Subíndice',
|
||||
'text_color' => 'Color de texto',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Color personalizado',
|
||||
'remove_color' => 'Eliminar color',
|
||||
'background_color' => 'Color de fondo',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Insertar Dibujo',
|
||||
'pages_md_show_preview' => 'Mostrar vista previa',
|
||||
'pages_md_sync_scroll' => 'Sincronizar desplazamiento de vista previa',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Encontrado dibujo sin guardar',
|
||||
'pages_drawing_unsaved_confirm' => 'Se encontraron datos no guardados del dibujo de un intento de guardado fallido. ¿Desea restaurar y continuar editando el dibujo no guardado?',
|
||||
'pages_not_in_chapter' => 'La página no está en un capítulo',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Superíndice',
|
||||
'subscript' => 'Subíndice',
|
||||
'text_color' => 'Color del texto',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Color personalizado',
|
||||
'remove_color' => 'Eliminar color',
|
||||
'background_color' => 'Color de fondo',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Insertar Dibujo',
|
||||
'pages_md_show_preview' => 'Mostrar vista previa',
|
||||
'pages_md_sync_scroll' => 'Sincronizar desplazamiento de vista previa',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Encontrado dibujo sin guardar',
|
||||
'pages_drawing_unsaved_confirm' => 'Se encontraron datos del dibujo no guardados durante un intento de guardado fallido anterior. ¿Desea restaurar y continuar editando el dibujo no guardado?',
|
||||
'pages_not_in_chapter' => 'La página no esá en el capítulo',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Ülaindeks',
|
||||
'subscript' => 'Alaindeks',
|
||||
'text_color' => 'Teksti värv',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Kohandatud värv',
|
||||
'remove_color' => 'Eemalda värv',
|
||||
'background_color' => 'Taustavärv',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Lisa joonis',
|
||||
'pages_md_show_preview' => 'Näita eelvaadet',
|
||||
'pages_md_sync_scroll' => 'Sünkrooni eelvaate kerimine',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Leiti salvestamata joonis',
|
||||
'pages_drawing_unsaved_confirm' => 'Varasemast ebaõnnestunud salvestuskatsest leiti salvestamata joonis. Kas soovid salvestamata joonise taastada ja selle muutmist jätkata?',
|
||||
'pages_not_in_chapter' => 'Leht ei kuulu peatüki alla',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Gain-eskripta',
|
||||
'subscript' => 'Azpi-script',
|
||||
'text_color' => 'Testuaren kolorea',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Kolore pertsonalizatua',
|
||||
'remove_color' => 'Kolorea ezabatu',
|
||||
'background_color' => 'Atzeko planoaren kolorea',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Txertatu marrazki berria',
|
||||
'pages_md_show_preview' => 'Show preview',
|
||||
'pages_md_sync_scroll' => 'Sync preview scroll',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Unsaved Drawing Found',
|
||||
'pages_drawing_unsaved_confirm' => 'Unsaved drawing data was found from a previous failed drawing save attempt. Would you like to restore and continue editing this unsaved drawing?',
|
||||
'pages_not_in_chapter' => 'Page is not in a chapter',
|
||||
|
@@ -6,7 +6,7 @@
|
||||
return [
|
||||
|
||||
// Pages
|
||||
'page_create' => 'تاریخ ایجاد',
|
||||
'page_create' => 'صفحه ایجاد شد',
|
||||
'page_create_notification' => 'صفحه با موفقیت ایجاد شد',
|
||||
'page_update' => 'به روزرسانی صفحه',
|
||||
'page_update_notification' => 'صفحه با موفقیت به روزرسانی شد',
|
||||
@@ -85,12 +85,12 @@ return [
|
||||
'webhook_delete_notification' => 'وب هوک با موفقیت حذف شد',
|
||||
|
||||
// Imports
|
||||
'import_create' => 'created import',
|
||||
'import_create_notification' => 'Import successfully uploaded',
|
||||
'import_run' => 'updated import',
|
||||
'import_run_notification' => 'Content successfully imported',
|
||||
'import_delete' => 'deleted import',
|
||||
'import_delete_notification' => 'Import successfully deleted',
|
||||
'import_create' => 'ورودی ایجاد شد',
|
||||
'import_create_notification' => 'فایل با موفقیت آپلود شد',
|
||||
'import_run' => 'آیتم واردشده بروزرسانی شد',
|
||||
'import_run_notification' => 'محتوا با موفقیت انتقال یافت',
|
||||
'import_delete' => 'آیتم ورودی حدف شده',
|
||||
'import_delete_notification' => 'آیتم واردشده با موفقیت حذف شد',
|
||||
|
||||
// Users
|
||||
'user_create' => 'کاربر ایجاد شده',
|
||||
@@ -128,12 +128,12 @@ return [
|
||||
'comment_delete' => 'نظر حذف شده',
|
||||
|
||||
// Sort Rules
|
||||
'sort_rule_create' => 'created sort rule',
|
||||
'sort_rule_create_notification' => 'Sort rule successfully created',
|
||||
'sort_rule_update' => 'updated sort rule',
|
||||
'sort_rule_update_notification' => 'Sort rule successfully updated',
|
||||
'sort_rule_delete' => 'deleted sort rule',
|
||||
'sort_rule_delete_notification' => 'Sort rule successfully deleted',
|
||||
'sort_rule_create' => 'قانون مرتبسازی ایجاد شد',
|
||||
'sort_rule_create_notification' => 'قانون مرتبسازی با موفقیت ایجاد شد',
|
||||
'sort_rule_update' => 'قانون مرتبسازی بهروزرسانی شد',
|
||||
'sort_rule_update_notification' => 'قانون مرتبسازی با موفقیت بهروزرسانی شد',
|
||||
'sort_rule_delete' => 'قانون مرتبسازی حذف شد',
|
||||
'sort_rule_delete_notification' => 'قانون مرتبسازی با موفقیت حذف شد',
|
||||
|
||||
// Other
|
||||
'permissions_update' => 'به روزرسانی مجوزها',
|
||||
|
@@ -91,7 +91,7 @@ return [
|
||||
'mfa_option_totp_title' => 'برنامه ی موبایل',
|
||||
'mfa_option_totp_desc' => 'برای استفاده از احراز هویت چند عاملی به یک برنامه موبایلی نیاز دارید که از TOTP پشتیبانی کند، مانند Google Authenticator، Authy یا Microsoft Authenticator.',
|
||||
'mfa_option_backup_codes_title' => 'کدهای پشتیبان',
|
||||
'mfa_option_backup_codes_desc' => 'Generates a set of one-time-use backup codes which you\'ll enter on login to verify your identity. Make sure to store these in a safe & secure place.',
|
||||
'mfa_option_backup_codes_desc' => 'این فرایند مجموعهای از کدهای پشتیبان یکبار مصرف تولید میکند که هنگام ورود به سامانه جهت تأیید هویت باید از آنها استفاده کنید. توصیه میشود این کدها را در محلّی امن و محفوظ نگهداری نمایید.',
|
||||
'mfa_gen_confirm_and_enable' => 'تایید و فعال کنید',
|
||||
'mfa_gen_backup_codes_title' => 'راه اندازی کدهای پشتیبان',
|
||||
'mfa_gen_backup_codes_desc' => 'لیست کدهای زیر را در مکانی امن ذخیره کنید. هنگام دسترسی به سیستم، می توانید از یکی از کدها به عنوان مکانیزم احراز هویت دوم استفاده کنید.',
|
||||
|
@@ -30,8 +30,8 @@ return [
|
||||
'create' => 'ایجاد',
|
||||
'update' => 'بهروز رسانی',
|
||||
'edit' => 'ويرايش',
|
||||
'archive' => 'Archive',
|
||||
'unarchive' => 'Un-Archive',
|
||||
'archive' => 'انتقال به بایگانی',
|
||||
'unarchive' => 'فعّالسازی دوباره (خروج از بایگانی)',
|
||||
'sort' => 'مرتب سازی',
|
||||
'move' => 'جابجایی',
|
||||
'copy' => 'کپی',
|
||||
@@ -111,5 +111,5 @@ return [
|
||||
'terms_of_service' => 'شرایط خدمات',
|
||||
|
||||
// OpenSearch
|
||||
'opensearch_description' => 'Search :appName',
|
||||
'opensearch_description' => 'جستوجو در :appName',
|
||||
];
|
||||
|
@@ -34,8 +34,8 @@ return [
|
||||
'image_delete_success' => 'تصویر با موفقیت حذف شد',
|
||||
'image_replace' => 'جایگزینی تصویر',
|
||||
'image_replace_success' => 'تصویر با موفقیت به روز شد',
|
||||
'image_rebuild_thumbs' => 'Regenerate Size Variations',
|
||||
'image_rebuild_thumbs_success' => 'Image size variations successfully rebuilt!',
|
||||
'image_rebuild_thumbs' => 'بازتولید اندازههای گوناگونی از تصویر',
|
||||
'image_rebuild_thumbs_success' => 'اندازههای گوناگونی از تصویر با موفقیت بازتولید شدند.',
|
||||
|
||||
// Code Editor
|
||||
'code_editor' => 'ویرایش کد',
|
||||
|
@@ -13,7 +13,7 @@ return [
|
||||
'cancel' => 'لغو',
|
||||
'save' => 'ذخیره',
|
||||
'close' => 'بستن',
|
||||
'apply' => 'Apply',
|
||||
'apply' => 'اعمال',
|
||||
'undo' => 'برگشت',
|
||||
'redo' => 'از نو',
|
||||
'left' => 'چپ',
|
||||
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'بالانویسی',
|
||||
'subscript' => 'پایین نویسی',
|
||||
'text_color' => 'رنگ متن',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'رنگ دلخواه',
|
||||
'remove_color' => 'حذف رنگ',
|
||||
'background_color' => 'رنگ زمینه',
|
||||
@@ -82,9 +83,9 @@ return [
|
||||
'table_properties' => 'تنظیمات جدول',
|
||||
'table_properties_title' => 'تنظیمات جدول',
|
||||
'delete_table' => 'حذف جدول',
|
||||
'table_clear_formatting' => 'Clear table formatting',
|
||||
'resize_to_contents' => 'Resize to contents',
|
||||
'row_header' => 'Row header',
|
||||
'table_clear_formatting' => 'حذف قالببندی جدول',
|
||||
'resize_to_contents' => 'تغییر اندازه بر اساس محتوا',
|
||||
'row_header' => 'عنوان سطر',
|
||||
'insert_row_before' => 'افزودن سطر به قبل',
|
||||
'insert_row_after' => 'افزودن سطر به بعد',
|
||||
'delete_row' => 'حذف سطر',
|
||||
@@ -148,7 +149,7 @@ return [
|
||||
'url' => 'آدرس',
|
||||
'text_to_display' => 'متن جهت نمایش',
|
||||
'title' => 'عنوان',
|
||||
'browse_links' => 'Browse links',
|
||||
'browse_links' => 'مرور پیوندها',
|
||||
'open_link' => 'بازکردن لینک',
|
||||
'open_link_in' => 'باز کردن لینک در ...',
|
||||
'open_link_current' => 'پنجره کنونی',
|
||||
@@ -165,8 +166,8 @@ return [
|
||||
'about' => 'درباره ویرایشگر',
|
||||
'about_title' => 'درباره ویرایشگر WYSIWYG',
|
||||
'editor_license' => 'مجوز و حق کپی رایت ویرایشگر',
|
||||
'editor_lexical_license' => 'This editor is built as a fork of :lexicalLink which is distributed under the MIT license.',
|
||||
'editor_lexical_license_link' => 'Full license details can be found here.',
|
||||
'editor_lexical_license' => 'این ویرایشگر بر پایهی نسخهای مشتقشده از «:lexicalLink» ساخته شده است که تحت مجوز MIT منتشر میشود.',
|
||||
'editor_lexical_license_link' => 'جزئیات کامل مجوز را میتوانید اینجا مشاهده کنید.',
|
||||
'editor_tiny_license' => 'این ویرایشگر توسط :tinyLink و تحت مجوز MIT ساخته شده است.',
|
||||
'editor_tiny_license_link' => 'جزئیات کپی رایت و مجوز TinyMCE را می توانید در اینجا پیدا کنید.',
|
||||
'save_continue' => 'ذخیره صفحه و ادامه',
|
||||
|
@@ -39,30 +39,30 @@ return [
|
||||
'export_pdf' => 'فایل PDF',
|
||||
'export_text' => 'پرونده متنی ساده',
|
||||
'export_md' => 'راهنما مارکدون',
|
||||
'export_zip' => 'Portable ZIP',
|
||||
'default_template' => 'Default Page Template',
|
||||
'default_template_explain' => 'Assign a page template that will be used as the default content for all pages created within this item. Keep in mind this will only be used if the page creator has view access to the chosen template page.',
|
||||
'default_template_select' => 'Select a template page',
|
||||
'import' => 'Import',
|
||||
'import_validate' => 'Validate Import',
|
||||
'import_desc' => 'Import books, chapters & pages using a portable zip export from the same, or a different, instance. Select a ZIP file to proceed. After the file has been uploaded and validated you\'ll be able to configure & confirm the import in the next view.',
|
||||
'import_zip_select' => 'Select ZIP file to upload',
|
||||
'import_zip_validation_errors' => 'Errors were detected while validating the provided ZIP file:',
|
||||
'import_pending' => 'Pending Imports',
|
||||
'import_pending_none' => 'No imports have been started.',
|
||||
'import_continue' => 'Continue Import',
|
||||
'import_continue_desc' => 'Review the content due to be imported from the uploaded ZIP file. When ready, run the import to add its contents to this system. The uploaded ZIP import file will be automatically removed on successful import.',
|
||||
'import_details' => 'Import Details',
|
||||
'import_run' => 'Run Import',
|
||||
'import_size' => ':size Import ZIP Size',
|
||||
'import_uploaded_at' => 'Uploaded :relativeTime',
|
||||
'import_uploaded_by' => 'Uploaded by',
|
||||
'import_location' => 'Import Location',
|
||||
'import_location_desc' => 'Select a target location for your imported content. You\'ll need the relevant permissions to create within the location you choose.',
|
||||
'import_delete_confirm' => 'Are you sure you want to delete this import?',
|
||||
'import_delete_desc' => 'This will delete the uploaded import ZIP file, and cannot be undone.',
|
||||
'import_errors' => 'Import Errors',
|
||||
'import_errors_desc' => 'The follow errors occurred during the import attempt:',
|
||||
'export_zip' => 'فایل فشردهی قابلحمل (ZIP)',
|
||||
'default_template' => 'قالب پیشفرض صفحه',
|
||||
'default_template_explain' => 'قالبی برای صفحه تعیین کنید که بهعنوان محتوای پیشفرض در تمام صفحاتی که در این مورد ایجاد میشوند، بهکار رود. توجه داشته باشید این قالب تنها در صورتی اعمال میشود که سازندهٔ صفحه به صفحهٔ قالب انتخابشده دسترسی نمایشی داشته باشد.',
|
||||
'default_template_select' => 'انتخاب صفحهٔ قالب',
|
||||
'import' => 'وارد کردن',
|
||||
'import_validate' => 'اعتبارسنجی آیتمهای واردشده',
|
||||
'import_desc' => 'میتوانید کتابها، فصلها و صفحات را با استفاده از یک فایل فشرده (ZIP) که از همین سامانه یا نمونهای دیگر استخراج شده، وارد کنید. برای ادامه، یک فایل ZIP انتخاب نمایید. پس از بارگذاری و اعتبارسنجی فایل، در مرحله بعد میتوانید تنظیمات انتقال را انجام داده و انتقال را تأیید کنید.',
|
||||
'import_zip_select' => 'انتخاب فایل ZIP برای بارگذاری',
|
||||
'import_zip_validation_errors' => 'هنگام اعتبارسنجی فایل ZIP ارائهشده، خطاهایی شناسایی شد:',
|
||||
'import_pending' => 'ورودیهای در انتظار انتقال',
|
||||
'import_pending_none' => 'هیچ انتقال ورودی آغاز نشده است.',
|
||||
'import_continue' => 'ادامه فرآیند انتقال ورودی',
|
||||
'import_continue_desc' => 'محتوای فایل ZIP بارگذاریشده را که قرار است وارد سامانه شود، مرور کنید. پس از اطمینان از صحت آن، انتقال را آغاز نمایید تا محتوا به این سامانه افزوده شود. توجه داشته باشید که پس از انتقال موفق، فایل ZIP بارگذاریشده بهصورت خودکار حذف خواهد شد.',
|
||||
'import_details' => 'جزئیات انتقال ورودی',
|
||||
'import_run' => 'شروع فرایند انتقال ورودی',
|
||||
'import_size' => 'حجم فایل ZIP واردشده: :size',
|
||||
'import_uploaded_at' => 'زمان بارگذاری: :relativeTime',
|
||||
'import_uploaded_by' => 'بارگذاری شده توسط:',
|
||||
'import_location' => 'مکان انتقال',
|
||||
'import_location_desc' => 'برای محتوای واردشده، مقصدی انتخاب کنید. برای ایجاد محتوا در آن مقصد، داشتن مجوزهای لازم ضروری است.',
|
||||
'import_delete_confirm' => 'مطمئن هستید که میخواهید آیتم واردشده را حدف کنید؟',
|
||||
'import_delete_desc' => 'با انجام این کار، فایل ZIP واردشده حذف میشود و این عمل بازگشتناپذیر است.',
|
||||
'import_errors' => 'خطای انتقال ورودی',
|
||||
'import_errors_desc' => 'در جریان تلاش برای انتقال ورودی، خطاهای زیر رخ داد:',
|
||||
|
||||
// Permissions and restrictions
|
||||
'permissions' => 'مجوزها',
|
||||
@@ -166,9 +166,9 @@ return [
|
||||
'books_search_this' => 'این کتاب را جستجو کنید',
|
||||
'books_navigation' => 'ناوبری کتاب',
|
||||
'books_sort' => 'مرتب سازی مطالب کتاب',
|
||||
'books_sort_desc' => 'Move chapters and pages within a book to reorganise its contents. Other books can be added which allows easy moving of chapters and pages between books. Optionally an auto sort rule can be set to automatically sort this book\'s contents upon changes.',
|
||||
'books_sort_auto_sort' => 'Auto Sort Option',
|
||||
'books_sort_auto_sort_active' => 'Auto Sort Active: :sortName',
|
||||
'books_sort_desc' => 'برای ساماندهی محتوای یک کتاب، میتوانید فصلها و صفحات آن را جابهجا کنید. همچنین میتوانید کتابهای دیگری بیفزایید تا جابهجایی فصلها و صفحات میان کتابها آسان شود. در صورت تمایل، میتوانید قاعدهای برای مرتبسازی خودکار تعیین کنید تا محتوای کتاب در صورت ایجاد تغییرات، به طور خودکار مرتب شود.',
|
||||
'books_sort_auto_sort' => 'گزینه مرتبسازی خودکار',
|
||||
'books_sort_auto_sort_active' => 'مرتبسازی خودکار با قاعده: :sortName فعال است',
|
||||
'books_sort_named' => 'مرتبسازی کتاب:bookName',
|
||||
'books_sort_name' => 'مرتب سازی بر اساس نام',
|
||||
'books_sort_created' => 'مرتب سازی بر اساس تاریخ ایجاد',
|
||||
@@ -230,7 +230,9 @@ return [
|
||||
'pages_delete_draft' => 'حذف صفحه پیش نویس',
|
||||
'pages_delete_success' => 'صفحه حذف شد',
|
||||
'pages_delete_draft_success' => 'صفحه پیش نویس حذف شد',
|
||||
'pages_delete_warning_template' => 'This page is in active use as a book or chapter default page template. These books or chapters will no longer have a default page template assigned after this page is deleted.',
|
||||
'pages_delete_warning_template' => 'این صفحه هماکنون بهعنوان قالب پیشفرض صفحه برای یک کتاب یا فصل در حال استفاده است. پس از حذف این صفحه، کتابها یا فصلهای مربوطه دیگر قالب پیشفرض صفحه نخواهند داشت.
|
||||
|
||||
',
|
||||
'pages_delete_confirm' => 'آیا مطمئن هستید که می خواهید این صفحه را حذف کنید؟',
|
||||
'pages_delete_draft_confirm' => 'آیا مطمئن هستید که می خواهید این صفحه پیش نویس را حذف کنید؟',
|
||||
'pages_editing_named' => 'ویرایش صفحه :pageName',
|
||||
@@ -247,8 +249,9 @@ return [
|
||||
'pages_edit_switch_to_markdown_clean' => '(مطالب تمیز)',
|
||||
'pages_edit_switch_to_markdown_stable' => '(محتوای پایدار)',
|
||||
'pages_edit_switch_to_wysiwyg' => 'به ویرایشگر WYSIWYG بروید',
|
||||
'pages_edit_switch_to_new_wysiwyg' => 'Switch to new WYSIWYG',
|
||||
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)',
|
||||
'pages_edit_switch_to_new_wysiwyg' => 'تغییر به ویرایشگر جدید WYSIWYG
|
||||
(ویرایشگر WYSIWYG: «آنچه میبینید همان است که بهدست میآورید»)',
|
||||
'pages_edit_switch_to_new_wysiwyg_desc' => '(در مرحله آزمایش بتا)',
|
||||
'pages_edit_set_changelog' => 'تنظیم تغییرات',
|
||||
'pages_edit_enter_changelog_desc' => 'توضیح مختصری از تغییراتی که ایجاد کرده اید وارد کنید',
|
||||
'pages_edit_enter_changelog' => 'وارد کردن تغییرات',
|
||||
@@ -268,6 +271,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'درج طرح',
|
||||
'pages_md_show_preview' => 'دیدن پیش نمایش',
|
||||
'pages_md_sync_scroll' => 'هماهنگ سازی اسکرول پیش نمایش',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'نقاشی ذخیره نشده پیدا شد',
|
||||
'pages_drawing_unsaved_confirm' => 'نسخهای ذخیرهنشده از طراحیهای قبلی پیدا شد. آیا میخواهید این طراحی ذخیرهنشده را بازیابی کنید و به ویرایش آن ادامه دهید؟',
|
||||
'pages_not_in_chapter' => 'صفحه در یک فصل نیست',
|
||||
@@ -301,9 +305,9 @@ return [
|
||||
'pages_pointer_enter_mode' => 'ورود به حالت انتخاب قسمت',
|
||||
'pages_pointer_label' => 'گزینههای قسمت صفحه',
|
||||
'pages_pointer_permalink' => 'لینک ثابت قسمت صفحه',
|
||||
'pages_pointer_include_tag' => 'Page Section Include Tag',
|
||||
'pages_pointer_toggle_link' => 'Permalink mode, Press to show include tag',
|
||||
'pages_pointer_toggle_include' => 'Include tag mode, Press to show permalink',
|
||||
'pages_pointer_include_tag' => 'افزودن برچسب برای این بخش از صفحه',
|
||||
'pages_pointer_toggle_link' => 'حالت پیوند دائمی؛ برای مشاهده برچسب افزوده شده، کلیک کنید',
|
||||
'pages_pointer_toggle_include' => 'حالت افزودن برچسب؛ برای نمایش پیوند دائمی کلیک کنید',
|
||||
'pages_permissions_active' => 'مجوزهای صفحه فعال است',
|
||||
'pages_initial_revision' => 'انتشار اولیه',
|
||||
'pages_references_update_revision' => 'بهروزرسانی خودکار لینکهای داخلی سیستم',
|
||||
@@ -324,7 +328,7 @@ return [
|
||||
'pages_is_template' => 'الگوی صفحه',
|
||||
|
||||
// Editor Sidebar
|
||||
'toggle_sidebar' => 'Toggle Sidebar',
|
||||
'toggle_sidebar' => 'نمایش/پنهانسازی نوار کناری',
|
||||
'page_tags' => 'برچسبهای صفحه',
|
||||
'chapter_tags' => 'برچسبهای فصل',
|
||||
'book_tags' => 'برچسب های کتاب',
|
||||
@@ -392,11 +396,11 @@ return [
|
||||
'comment' => 'اظهار نظر',
|
||||
'comments' => 'نظرات',
|
||||
'comment_add' => 'افزودن توضیح',
|
||||
'comment_none' => 'No comments to display',
|
||||
'comment_none' => 'نظری برای نمایش وجود ندارد',
|
||||
'comment_placeholder' => 'اینجا نظر بدهید',
|
||||
'comment_thread_count' => ':count Comment Thread|:count Comment Threads',
|
||||
'comment_archived_count' => ':count Archived',
|
||||
'comment_archived_threads' => 'Archived Threads',
|
||||
'comment_thread_count' => ':count رشته گفتوگو',
|
||||
'comment_archived_count' => ':count مورد بایگانیشده',
|
||||
'comment_archived_threads' => 'رشته گفتوگوهای بایگانیشده',
|
||||
'comment_save' => 'ذخیره نظر',
|
||||
'comment_new' => 'نظر جدید',
|
||||
'comment_created' => ':createDiff نظر داد',
|
||||
@@ -405,14 +409,14 @@ return [
|
||||
'comment_deleted_success' => 'نظر حذف شد',
|
||||
'comment_created_success' => 'نظر اضافه شد',
|
||||
'comment_updated_success' => 'نظر به روز شد',
|
||||
'comment_archive_success' => 'Comment archived',
|
||||
'comment_unarchive_success' => 'Comment un-archived',
|
||||
'comment_view' => 'View comment',
|
||||
'comment_jump_to_thread' => 'Jump to thread',
|
||||
'comment_archive_success' => 'نظر بایگانی شد',
|
||||
'comment_unarchive_success' => 'نظر از بایگانی خارج شد',
|
||||
'comment_view' => 'دیدن نظر',
|
||||
'comment_jump_to_thread' => 'رفتن به رشته گفتوگو',
|
||||
'comment_delete_confirm' => 'آیا مطمئن هستید که می خواهید این نظر را حذف کنید؟',
|
||||
'comment_in_reply_to' => 'در پاسخ به :commentId',
|
||||
'comment_reference' => 'Reference',
|
||||
'comment_reference_outdated' => '(Outdated)',
|
||||
'comment_reference' => 'مرجع',
|
||||
'comment_reference_outdated' => '(نسخه قدیمی)',
|
||||
'comment_editor_explain' => 'در اینجا نظراتی که در این صفحه گذاشته شده است، مشاهده میشود. نظرات را میتوان در هنگام مشاهده صفحه ذخیره شده، اضافه و مدیریت کرد.',
|
||||
|
||||
// Revision
|
||||
|
@@ -18,10 +18,10 @@ return [
|
||||
'ldap_fail_anonymous' => 'دسترسی LDAP با استفاده از صحافی ناشناس انجام نشد',
|
||||
'ldap_fail_authed' => 'دسترسی به LDAP با استفاده از جزئیات داده شده و رمز عبور انجام نشد',
|
||||
'ldap_extension_not_installed' => 'افزونه PHP LDAP نصب نشده است',
|
||||
'ldap_cannot_connect' => 'اتصال به سرور LDAP امکان پذیر نیست، اتصال اولیه برقرار نشد',
|
||||
'ldap_cannot_connect' => 'اتصال به سرور LDAP امکانپذیر نیست، اتصال اولیه برقرار نشد',
|
||||
'saml_already_logged_in' => 'قبلا وارد سیستم شده اید',
|
||||
'saml_no_email_address' => 'آدرس داده ای برای این کاربر در داده های ارائه شده توسط سیستم احراز هویت خارجی یافت نشد',
|
||||
'saml_invalid_response_id' => 'درخواست از سیستم احراز هویت خارجی توسط فرایندی که توسط این نرم افزار آغاز شده است شناخته نمی شود. بازگشت به سیستم پس از ورود به سیستم می تواند باعث این مسئله شود.',
|
||||
'saml_invalid_response_id' => 'درخواست ارسالشده از سامانه احراز هویت خارجی، توسط فرآیند آغازشده از سوی این نرمافزار شناسایی نشد. ممکن است بازگشت به صفحه قبل پس از ورود، موجب ایجاد این مشکل شده باشد.',
|
||||
'saml_fail_authed' => 'ورود به سیستم :system انجام نشد، سیستم مجوز موفقیت آمیز ارائه نکرد',
|
||||
'oidc_already_logged_in' => 'قبلا وارد شده اید',
|
||||
'oidc_no_email_address' => 'آدرس ایمیلی برای این کاربر در داده های ارائه شده توسط سیستم احراز هویت خارجی یافت نشد',
|
||||
@@ -43,7 +43,7 @@ return [
|
||||
'path_not_writable' => 'مسیر فایل :filePath را نمی توان در آن آپلود کرد. مطمئن شوید که روی سرور قابل نوشتن است.',
|
||||
'cannot_get_image_from_url' => 'نمی توان تصویر را از :url دریافت کرد',
|
||||
'cannot_create_thumbs' => 'سرور نمی تواند تصاویر کوچک ایجاد کند. لطفاً بررسی کنید که پسوند GD PHP را نصب کرده اید.',
|
||||
'server_upload_limit' => 'سرور اجازه آپلود در این اندازه را نمی دهد. لطفا اندازه فایل کوچکتر را امتحان کنید.',
|
||||
'server_upload_limit' => 'سرور اجازه آپلود با این حجم را نمی دهد. لطفا فایلی با حجم کمتر را امتحان کنید.',
|
||||
'server_post_limit' => 'سرور نمیتواند داده مقادیر ارائه شده داده را دریافت کند. با مقدار کمتر و فایل کوچکتر دوباره امتحان کنید.',
|
||||
'uploaded' => 'سرور اجازه آپلود در این اندازه را نمی دهد. لطفا اندازه فایل کوچکتر را امتحان کنید.',
|
||||
|
||||
@@ -78,7 +78,7 @@ return [
|
||||
// Users
|
||||
'users_cannot_delete_only_admin' => 'شما نمی توانید تنها ادمین را حذف کنید',
|
||||
'users_cannot_delete_guest' => 'شما نمی توانید کاربر مهمان را حذف کنید',
|
||||
'users_could_not_send_invite' => 'Could not create user since invite email failed to send',
|
||||
'users_could_not_send_invite' => 'امکان ایجاد کاربر وجود ندارد؛ زیرا ارسال ایمیل دعوت با خطا مواجه شد.',
|
||||
|
||||
// Roles
|
||||
'role_cannot_be_edited' => 'این نقش قابل ویرایش نیست',
|
||||
@@ -106,16 +106,16 @@ return [
|
||||
'back_soon' => 'به زودی پشتیبان خواهد شد.',
|
||||
|
||||
// Import
|
||||
'import_zip_cant_read' => 'Could not read ZIP file.',
|
||||
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.',
|
||||
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.',
|
||||
'import_validation_failed' => 'Import ZIP failed to validate with errors:',
|
||||
'import_zip_failed_notification' => 'Failed to import ZIP file.',
|
||||
'import_perms_books' => 'You are lacking the required permissions to create books.',
|
||||
'import_perms_chapters' => 'You are lacking the required permissions to create chapters.',
|
||||
'import_perms_pages' => 'You are lacking the required permissions to create pages.',
|
||||
'import_perms_images' => 'You are lacking the required permissions to create images.',
|
||||
'import_perms_attachments' => 'You are lacking the required permission to create attachments.',
|
||||
'import_zip_cant_read' => 'امکان ایجاد کاربر وجود ندارد؛ زیرا ارسال ایمیل دعوت با خطا مواجه شد.',
|
||||
'import_zip_cant_decode_data' => 'محتوای data.json در فایل ZIP پیدا یا رمزگشایی نشد.',
|
||||
'import_zip_no_data' => 'دادههای فایل ZIP فاقد محتوای کتاب، فصل یا صفحه مورد انتظار است.',
|
||||
'import_validation_failed' => 'اعتبارسنجی فایل ZIP واردشده با خطا مواجه شد:',
|
||||
'import_zip_failed_notification' => ' فایل ZIP وارد نشد.',
|
||||
'import_perms_books' => 'شما مجوز لازم برای ایجاد کتاب را ندارید.',
|
||||
'import_perms_chapters' => 'شما مجوز لازم برای ایجاد فصل را ندارید.',
|
||||
'import_perms_pages' => 'شما مجوز لازم برای ایجاد صفحه را ندارید.',
|
||||
'import_perms_images' => 'شما مجوز لازم برای ایجاد تصویر را ندارید.',
|
||||
'import_perms_attachments' => 'شما مجوز لازم برای ایجاد پیوست را ندارید.',
|
||||
|
||||
// API errors
|
||||
'api_no_authorization_found' => 'هیچ نشانه مجوزی در درخواست یافت نشد',
|
||||
|
@@ -22,6 +22,6 @@ return [
|
||||
'action_view_comment' => 'مشاهده نظر',
|
||||
'action_view_page' => 'مشاهده صفحه',
|
||||
|
||||
'footer_reason' => 'This notification was sent to you because :link cover this type of activity for this item.',
|
||||
'footer_reason' => 'این اعلان برای شما ارسال شده است، زیرا پیوند (:link) فعالیتی از این نوع را برای این مورد پوشش میدهد.',
|
||||
'footer_reason_link' => 'تنظیمات اطلاعرسانی شما',
|
||||
];
|
||||
|
@@ -15,7 +15,7 @@ return [
|
||||
// App Settings
|
||||
'app_customization' => 'سفارشیسازی',
|
||||
'app_features_security' => 'ویژگیها و امنیت',
|
||||
'app_name' => 'نام نرم افزار',
|
||||
'app_name' => 'نام نرمافزار',
|
||||
'app_name_desc' => 'این نام در هدر و در هر ایمیل ارسال شده توسط سیستم نشان داده شده است.',
|
||||
'app_name_header' => 'نمایش نام در هدر',
|
||||
'app_public_access' => 'دسترسی عمومی',
|
||||
@@ -75,34 +75,34 @@ return [
|
||||
'reg_confirm_restrict_domain_placeholder' => 'بدون محدودیت',
|
||||
|
||||
// Sorting Settings
|
||||
'sorting' => 'Sorting',
|
||||
'sorting_book_default' => 'Default Book Sort',
|
||||
'sorting_book_default_desc' => 'Select the default sort rule to apply to new books. This won\'t affect existing books, and can be overridden per-book.',
|
||||
'sorting_rules' => 'Sort Rules',
|
||||
'sorting_rules_desc' => 'These are predefined sorting operations which can be applied to content in the system.',
|
||||
'sort_rule_assigned_to_x_books' => 'Assigned to :count Book|Assigned to :count Books',
|
||||
'sort_rule_create' => 'Create Sort Rule',
|
||||
'sort_rule_edit' => 'Edit Sort Rule',
|
||||
'sort_rule_delete' => 'Delete Sort Rule',
|
||||
'sort_rule_delete_desc' => 'Remove this sort rule from the system. Books using this sort will revert to manual sorting.',
|
||||
'sort_rule_delete_warn_books' => 'This sort rule is currently used on :count book(s). Are you sure you want to delete this?',
|
||||
'sort_rule_delete_warn_default' => 'This sort rule is currently used as the default for books. Are you sure you want to delete this?',
|
||||
'sort_rule_details' => 'Sort Rule Details',
|
||||
'sort_rule_details_desc' => 'Set a name for this sort rule, which will appear in lists when users are selecting a sort.',
|
||||
'sort_rule_operations' => 'Sort Operations',
|
||||
'sort_rule_operations_desc' => 'Configure the sort actions to be performed by moving them from the list of available operations. Upon use, the operations will be applied in order, from top to bottom. Any changes made here will be applied to all assigned books upon save.',
|
||||
'sort_rule_available_operations' => 'Available Operations',
|
||||
'sort_rule_available_operations_empty' => 'No operations remaining',
|
||||
'sort_rule_configured_operations' => 'Configured Operations',
|
||||
'sort_rule_configured_operations_empty' => 'Drag/add operations from the "Available Operations" list',
|
||||
'sort_rule_op_asc' => '(Asc)',
|
||||
'sort_rule_op_desc' => '(Desc)',
|
||||
'sort_rule_op_name' => 'Name - Alphabetical',
|
||||
'sort_rule_op_name_numeric' => 'Name - Numeric',
|
||||
'sort_rule_op_created_date' => 'Created Date',
|
||||
'sort_rule_op_updated_date' => 'Updated Date',
|
||||
'sort_rule_op_chapters_first' => 'Chapters First',
|
||||
'sort_rule_op_chapters_last' => 'Chapters Last',
|
||||
'sorting' => 'مرتبسازی',
|
||||
'sorting_book_default' => 'مرتبسازی پیشفرض کتاب',
|
||||
'sorting_book_default_desc' => 'قانون پیشفرض مرتبسازی را برای کتابهای جدید انتخاب کنید. تغییر قانون بر ترتیب کتابهای موجود تأثیری ندارد و میتواند برای هر کتاب بهصورت جداگانه تغییر یابد.',
|
||||
'sorting_rules' => 'قوانین مرتبسازی',
|
||||
'sorting_rules_desc' => 'اینها عملیات مرتبسازی از پیش تعریفشدهای هستند که میتوانید آنها را بر محتوای سیستم اعمال کنید.',
|
||||
'sort_rule_assigned_to_x_books' => 'اختصاص داده شده به :count کتاب',
|
||||
'sort_rule_create' => 'ایجاد قانون مرتبسازی',
|
||||
'sort_rule_edit' => 'ویرایش قانون مرتبسازی',
|
||||
'sort_rule_delete' => 'حذف قانون مرتبسازی',
|
||||
'sort_rule_delete_desc' => 'این قانون مرتبسازی را از سیستم حذف کنید. کتابهایی که از این شیوه مرتبسازی استفاده میکنند، به حالت مرتبسازی دستی بازخواهند گشت.',
|
||||
'sort_rule_delete_warn_books' => 'در حال حاضر این قانون مرتبسازی برای :count کتاب بهکار میرود. آیا مطمئن هستید که میخواهید آن را حذف کنید؟',
|
||||
'sort_rule_delete_warn_default' => 'این قانون مرتبسازی هماکنون به عنوان پیشفرض کتابها تعیین شده است. آیا مطمئن هستید که میخواهید آن را حذف کنید؟',
|
||||
'sort_rule_details' => 'جزئیات قانون مرتبسازی',
|
||||
'sort_rule_details_desc' => 'برای این قانون مرتبسازی یک نام انتخاب کنید. این نام هنگام انتخاب شیوه مرتبسازی در فهرستها نمایش داده خواهد شد.',
|
||||
'sort_rule_operations' => 'عملیات مرتبسازی',
|
||||
'sort_rule_operations_desc' => 'عملیات مرتبسازی را پیکربندی کنید. برای این منظور، آنها را در فهرست عملیاتِ در دسترس جابهجا کنید تا ترتیب اجرای آنها مشخص شود. هنگام استفاده، این عملیات بهترتیب از بالا به پایین اعمال خواهند شد. هر تغییری که در این بخش ایجاد کنید، پس از ذخیره، برای همه کتابهای اختصاصیافته اجرا میشود.',
|
||||
'sort_rule_available_operations' => 'عملیات موجود',
|
||||
'sort_rule_available_operations_empty' => 'عملیاتی باقی نمانده است',
|
||||
'sort_rule_configured_operations' => 'عملیات پیکربندیشده',
|
||||
'sort_rule_configured_operations_empty' => 'عملیات را از فهرست «عملیات موجود» حذف یا اضافه کنید',
|
||||
'sort_rule_op_asc' => '(صعودی)',
|
||||
'sort_rule_op_desc' => '(نزولی)',
|
||||
'sort_rule_op_name' => 'نام - الفبایی',
|
||||
'sort_rule_op_name_numeric' => 'نام - عددی',
|
||||
'sort_rule_op_created_date' => 'تاریخ ایجاد',
|
||||
'sort_rule_op_updated_date' => 'تاریخ بهروزرسانی',
|
||||
'sort_rule_op_chapters_first' => 'ابتدا فصلها',
|
||||
'sort_rule_op_chapters_last' => 'فصلها در آخر',
|
||||
|
||||
// Maintenance settings
|
||||
'maint' => 'نگهداری',
|
||||
@@ -192,7 +192,7 @@ return [
|
||||
'role_access_api' => 'دسترسی به API سیستم',
|
||||
'role_manage_settings' => 'تنظیمات برنامه را مدیریت کنید',
|
||||
'role_export_content' => 'صادرات محتوا',
|
||||
'role_import_content' => 'Import content',
|
||||
'role_import_content' => 'وارد کردن محتوا',
|
||||
'role_editor_change' => 'تغییر ویرایشگر صفحه',
|
||||
'role_notifications' => 'دریافت و مدیریت اعلانها',
|
||||
'role_asset' => 'مجوزهای دارایی',
|
||||
|
@@ -105,10 +105,10 @@ return [
|
||||
'url' => ':attribute معتبر نمیباشد.',
|
||||
'uploaded' => 'بارگذاری فایل :attribute موفقیت آمیز نبود.',
|
||||
|
||||
'zip_file' => 'The :attribute needs to reference a file within the ZIP.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
'zip_file' => 'ویژگی :attribute باید به یک فایل درون پرونده فشرده شده اشاره کند.',
|
||||
'zip_file_mime' => 'ویژگی :attribute باید به فایلی با نوع :validTypes اشاره کند، اما نوع یافتشده :foundType است.',
|
||||
'zip_model_expected' => 'سیستم در این بخش انتظار دریافت یک شیء دادهای را داشت، اما «:type» دریافت گردید',
|
||||
'zip_unique' => 'برای هر نوع شیء در فایل ZIP، مقدار ویژگی :attribute باید یکتا و بدون تکرار باشد.',
|
||||
|
||||
// Custom validation lines
|
||||
'custom' => [
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Yläindeksi',
|
||||
'subscript' => 'Alaindeksi',
|
||||
'text_color' => 'Tekstin väri',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Mukautettu väri',
|
||||
'remove_color' => 'Poista väri',
|
||||
'background_color' => 'Taustaväri',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Lisää piirustus',
|
||||
'pages_md_show_preview' => 'Näytä esikatselu',
|
||||
'pages_md_sync_scroll' => 'Vieritä esikatselua koodin vierityksen mukaan',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Tallentamaton piirustus löytyi',
|
||||
'pages_drawing_unsaved_confirm' => 'Järjestelmä löysi tallentamattoman piirustuksen. Haluatko palauttaa piirustuksen ja jatkaa sen muokkaamista?',
|
||||
'pages_not_in_chapter' => 'Sivu ei kuulu mihinkään lukuun',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Exposant',
|
||||
'subscript' => 'Indice',
|
||||
'text_color' => 'Couleur Texte',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Couleur personnalisée',
|
||||
'remove_color' => 'Supprimer la couleur',
|
||||
'background_color' => 'Couleur d\'arrière-plan',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Insérer un dessin',
|
||||
'pages_md_show_preview' => 'Prévisualisation',
|
||||
'pages_md_sync_scroll' => 'Défilement prévisualisation',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Dessin non enregistré trouvé',
|
||||
'pages_drawing_unsaved_confirm' => 'Des données de dessin non enregistrées ont été trouvées à partir d\'une tentative de sauvegarde de dessin échouée. Voulez-vous restaurer et continuer à modifier ce dessin non sauvegardé ?',
|
||||
'pages_not_in_chapter' => 'La page n\'est pas dans un chapitre',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'כתב עילי',
|
||||
'subscript' => 'כתב תחתי',
|
||||
'text_color' => 'צבע טקסט',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'צבע מותאם',
|
||||
'remove_color' => 'הסר צבע',
|
||||
'background_color' => 'צבע רקע',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'הכנס סרטוט',
|
||||
'pages_md_show_preview' => 'Show preview',
|
||||
'pages_md_sync_scroll' => 'Sync preview scroll',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Unsaved Drawing Found',
|
||||
'pages_drawing_unsaved_confirm' => 'Unsaved drawing data was found from a previous failed drawing save attempt. Would you like to restore and continue editing this unsaved drawing?',
|
||||
'pages_not_in_chapter' => 'דף אינו חלק מפרק',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Gornji indeks',
|
||||
'subscript' => 'Donji indeks',
|
||||
'text_color' => 'Boja teksta',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Prilagođena boja',
|
||||
'remove_color' => 'Ukloni boju',
|
||||
'background_color' => 'Boja pozadine',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Umetni crtež',
|
||||
'pages_md_show_preview' => 'Prikaži pregled',
|
||||
'pages_md_sync_scroll' => 'Sinkroniziraj pomicanje pregleda',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Pronađen je Nespremljen Crtež',
|
||||
'pages_drawing_unsaved_confirm' => 'Pronađeni su nespremljeni podaci crteža iz prethodnog neuspjelog pokušaja spremanja crteža. Želite li obnoviti i nastaviti uređivati ovaj nespremljeni crtež?',
|
||||
'pages_not_in_chapter' => 'Stranica nije u poglavlju',
|
||||
|
@@ -48,6 +48,7 @@ return [
|
||||
'superscript' => 'Felső index',
|
||||
'subscript' => 'Alsó index',
|
||||
'text_color' => 'Szöveg szín',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'custom_color' => 'Egyéni szín',
|
||||
'remove_color' => 'Szín eltávolítása',
|
||||
'background_color' => 'Háttérszín',
|
||||
|
@@ -268,6 +268,7 @@ return [
|
||||
'pages_md_insert_drawing' => 'Rajz beillesztése',
|
||||
'pages_md_show_preview' => 'Előnézet megjelenítése',
|
||||
'pages_md_sync_scroll' => 'Előnézet pozíció szinkronizálása',
|
||||
'pages_md_plain_editor' => 'Plaintext editor',
|
||||
'pages_drawing_unsaved' => 'Nem mentett rajz található',
|
||||
'pages_drawing_unsaved_confirm' => 'A rendszer nem mentett rajzadatokat talált egy korábbi sikertelen rajzmentési kísérletből. Szeretné visszaállítani és folytatni a nem mentett rajz szerkesztését?',
|
||||
'pages_not_in_chapter' => 'Az oldal nincs fejezetben',
|
||||
|
@@ -72,7 +72,7 @@ return [
|
||||
'mfa_remove_method_notification' => 'Metode multi-faktor sukses dihapus',
|
||||
|
||||
// Settings
|
||||
'settings_update' => 'updated settings',
|
||||
'settings_update' => 'memperbarui setelan',
|
||||
'settings_update_notification' => 'Pengaturan berhasil diperbarui',
|
||||
'maintenance_action_run' => 'menjalankan tindakan pemeliharaan',
|
||||
|
||||
@@ -85,12 +85,12 @@ return [
|
||||
'webhook_delete_notification' => 'Webhook berhasil dihapus',
|
||||
|
||||
// Imports
|
||||
'import_create' => 'created import',
|
||||
'import_create_notification' => 'Import successfully uploaded',
|
||||
'import_run' => 'updated import',
|
||||
'import_run_notification' => 'Content successfully imported',
|
||||
'import_delete' => 'deleted import',
|
||||
'import_delete_notification' => 'Import successfully deleted',
|
||||
'import_create' => 'telat membuat impor',
|
||||
'import_create_notification' => 'Impor berhasil diunggah',
|
||||
'import_run' => 'telah memperbarui impor',
|
||||
'import_run_notification' => 'Konten berhasil diimpor',
|
||||
'import_delete' => 'telah menghapus impor',
|
||||
'import_delete_notification' => 'Impor berhasil dihapus',
|
||||
|
||||
// Users
|
||||
'user_create' => 'pengguna yang dibuat',
|
||||
@@ -109,31 +109,31 @@ return [
|
||||
'api_token_delete_notification' => 'token API berhasil dihapus ',
|
||||
|
||||
// Roles
|
||||
'role_create' => 'created role',
|
||||
'role_create' => 'telah membuat peran',
|
||||
'role_create_notification' => 'Peran berhasil dibuat',
|
||||
'role_update' => 'updated role',
|
||||
'role_update' => 'telah memperbarui peran',
|
||||
'role_update_notification' => 'Peran berhasil diperbarui',
|
||||
'role_delete' => 'deleted role',
|
||||
'role_delete' => 'telah menghapus peran',
|
||||
'role_delete_notification' => 'Peran berhasil dihapus',
|
||||
|
||||
// Recycle Bin
|
||||
'recycle_bin_empty' => 'emptied recycle bin',
|
||||
'recycle_bin_restore' => 'restored from recycle bin',
|
||||
'recycle_bin_destroy' => 'removed from recycle bin',
|
||||
'recycle_bin_empty' => 'telah mengosongkan tempat sampah',
|
||||
'recycle_bin_restore' => 'telah mengembalikan dari tempat sampah',
|
||||
'recycle_bin_destroy' => 'telah menghapus dari tempat sampah',
|
||||
|
||||
// Comments
|
||||
'commented_on' => 'berkomentar pada',
|
||||
'comment_create' => 'added comment',
|
||||
'comment_update' => 'updated comment',
|
||||
'comment_delete' => 'deleted comment',
|
||||
'comment_create' => 'telah menambah komentar',
|
||||
'comment_update' => 'telah memperbarui komentar',
|
||||
'comment_delete' => 'telah menghapus komentar',
|
||||
|
||||
// Sort Rules
|
||||
'sort_rule_create' => 'created sort rule',
|
||||
'sort_rule_create_notification' => 'Sort rule successfully created',
|
||||
'sort_rule_update' => 'updated sort rule',
|
||||
'sort_rule_update_notification' => 'Sort rule successfully updated',
|
||||
'sort_rule_delete' => 'deleted sort rule',
|
||||
'sort_rule_delete_notification' => 'Sort rule successfully deleted',
|
||||
'sort_rule_create' => 'telah membuat aturan penyortiran',
|
||||
'sort_rule_create_notification' => 'Aturan penyortiran berhasil dibuat',
|
||||
'sort_rule_update' => 'telah mengubah aturan penyortiran',
|
||||
'sort_rule_update_notification' => 'Aturan penyortiran berhasil diubah',
|
||||
'sort_rule_delete' => 'telah menghapus aturan penyortiran',
|
||||
'sort_rule_delete_notification' => 'Aturan penyortiran berhasil dihapus',
|
||||
|
||||
// Other
|
||||
'permissions_update' => 'izin diperbarui',
|
||||
|
@@ -86,32 +86,32 @@ return [
|
||||
'mfa_setup_configured' => 'Sudah dikonfigurasi',
|
||||
'mfa_setup_reconfigure' => 'Konfigurasi ulang',
|
||||
'mfa_setup_remove_confirmation' => 'Apakah Anda yakin ingin menghapus metode autentikasi multi-faktor ini?',
|
||||
'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_setup_action' => 'Atur',
|
||||
'mfa_backup_codes_usage_limit_warning' => 'Anda memiliki kurang dari 5 kode cadangan yang tersisa. Harap buat dan simpan set baru sebelum Anda kehabisan kode untuk mencegah akun Anda terkunci.',
|
||||
'mfa_option_totp_title' => 'Aplikasi Seluler',
|
||||
'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' => 'Untuk menggunakan autentikasi multi-faktor, Anda memerlukan aplikasi seluler yang mendukung TOTP seperti Google Authenticator, Authy, atau Microsoft Authenticator.',
|
||||
'mfa_option_backup_codes_title' => 'Kode Cadangan',
|
||||
'mfa_option_backup_codes_desc' => 'Generates a set of one-time-use backup codes which you\'ll enter on login to verify your identity. Make sure to store these in a safe & secure place.',
|
||||
'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_option_backup_codes_desc' => 'Menghasilkan serangkaian kode cadangan sekali pakai yang akan Anda masukkan saat masuk untuk memverifikasi identitas Anda. Pastikan untuk menyimpannya di tempat yang aman.',
|
||||
'mfa_gen_confirm_and_enable' => 'Konfirmasi dan Aktifkan',
|
||||
'mfa_gen_backup_codes_title' => 'Pengaturan Kode Cadangan',
|
||||
'mfa_gen_backup_codes_desc' => 'Simpan daftar kode di bawah ini di tempat yang aman. Saat mengakses sistem, Anda dapat menggunakan salah satu kode sebagai mekanisme autentikasi kedua.',
|
||||
'mfa_gen_backup_codes_download' => 'Unduh Kode',
|
||||
'mfa_gen_backup_codes_usage_warning' => 'Setiap kode hanya dapat digunakan satu kali',
|
||||
'mfa_gen_totp_title' => 'Pengaturan Aplikasi Seluler',
|
||||
'mfa_gen_totp_desc' => 'Untuk menggunakan autentikasi multi-faktor, Anda memerlukan aplikasi seluler yang mendukung TOTP seperti Google Authenticator, Authy, atau Microsoft Authenticator.',
|
||||
'mfa_gen_totp_scan' => 'Pindai kode QR di bawah ini menggunakan aplikasi autentikasi pilihan Anda untuk memulai.',
|
||||
'mfa_gen_totp_verify_setup' => 'Verifikasi Pengaturan',
|
||||
'mfa_gen_totp_verify_setup_desc' => 'Verifikasi bahwa semuanya berfungsi dengan memasukkan kode yang dibuat dalam aplikasi autentikasi Anda pada kolom input di bawah ini:',
|
||||
'mfa_gen_totp_provide_code_here' => 'Berikan kode yang dihasilkan aplikasi Anda di sini',
|
||||
'mfa_verify_access' => 'Verifikasi Akses',
|
||||
'mfa_verify_access_desc' => 'Akun pengguna Anda mengharuskan Anda mengonfirmasi identitas Anda melalui tingkat verifikasi tambahan sebelum Anda diberikan akses. Verifikasi menggunakan salah satu metode yang telah Anda konfigurasikan untuk melanjutkan.',
|
||||
'mfa_verify_no_methods' => 'Tidak Ada Metode yang Dikonfigurasi',
|
||||
'mfa_verify_no_methods_desc' => 'Tidak ada metode autentikasi multi-faktor yang ditemukan untuk akun Anda. Anda perlu menyiapkan setidaknya satu metode sebelum mendapatkan akses.',
|
||||
'mfa_verify_use_totp' => 'Verifikasi menggunakan aplikasi seluler',
|
||||
'mfa_verify_use_backup_codes' => 'Verifikasi menggunakan kode cadangan',
|
||||
'mfa_verify_backup_code' => 'Kode Cadangan',
|
||||
'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.',
|
||||
'mfa_verify_backup_code_desc' => 'Masukkan salah satu kode cadangan Anda yang tersisa di bawah ini:',
|
||||
'mfa_verify_backup_code_enter_here' => 'Masukkan kode cadangan di sini',
|
||||
'mfa_verify_totp_desc' => 'Masukkan kode yang dibuat menggunakan aplikasi seluler Anda di bawah ini:',
|
||||
'mfa_setup_login_notification' => 'Metode multi-faktor dikonfigurasi. Silakan masuk lagi menggunakan metode yang dikonfigurasi.',
|
||||
];
|
||||
|
@@ -6,7 +6,7 @@ return [
|
||||
|
||||
// Buttons
|
||||
'cancel' => 'Batal',
|
||||
'close' => 'Close',
|
||||
'close' => 'Tutup',
|
||||
'confirm' => 'Konfirmasi',
|
||||
'back' => 'Kembali',
|
||||
'save' => 'Simpan',
|
||||
@@ -20,18 +20,18 @@ return [
|
||||
'description' => 'Deskripsi',
|
||||
'role' => 'Peran',
|
||||
'cover_image' => 'Sampul gambar',
|
||||
'cover_image_description' => 'This image should be approximately 440x250px although it will be flexibly scaled & cropped to fit the user interface in different scenarios as required, so actual dimensions for display will differ.',
|
||||
'cover_image_description' => 'Gambar ini harus berukuran sekitar 440x250px walaupun nanti akan disesuaikan & terpotong secara fleksibel agar sesuai dengan tampilan pengguna, sehingga dimensi sebenarnya untuk tampilan akan berbeda.',
|
||||
|
||||
// Actions
|
||||
'actions' => 'Tindakan',
|
||||
'view' => 'Lihat',
|
||||
'view_all' => 'Lihat Semua',
|
||||
'new' => 'New',
|
||||
'new' => 'Buat Baru',
|
||||
'create' => 'Buat',
|
||||
'update' => 'Perbarui',
|
||||
'edit' => 'Sunting',
|
||||
'archive' => 'Archive',
|
||||
'unarchive' => 'Un-Archive',
|
||||
'archive' => 'Buat Arsip',
|
||||
'unarchive' => 'Batalkan Arsip',
|
||||
'sort' => 'Sortir',
|
||||
'move' => 'Pindahkan',
|
||||
'copy' => 'Salin',
|
||||
@@ -43,18 +43,18 @@ return [
|
||||
'reset' => 'Atur ulang',
|
||||
'remove' => 'Hapus',
|
||||
'add' => 'Tambah',
|
||||
'configure' => 'Configure',
|
||||
'manage' => 'Manage',
|
||||
'configure' => 'Atur',
|
||||
'manage' => 'Kelola',
|
||||
'fullscreen' => 'Layar Penuh',
|
||||
'favourite' => 'Favorit',
|
||||
'unfavourite' => 'Batal favorit',
|
||||
'next' => 'Selanjutnya',
|
||||
'previous' => 'Sebelumnya',
|
||||
'filter_active' => 'Active Filter:',
|
||||
'filter_clear' => 'Clear Filter',
|
||||
'download' => 'Download',
|
||||
'open_in_tab' => 'Open in Tab',
|
||||
'open' => 'Open',
|
||||
'filter_active' => 'Filter Aktif:',
|
||||
'filter_clear' => 'Hapus Filter',
|
||||
'download' => 'Unduh',
|
||||
'open_in_tab' => 'Buka di tab baru',
|
||||
'open' => 'Buka',
|
||||
|
||||
// Sort Options
|
||||
'sort_options' => 'Opsi Sortir',
|
||||
@@ -80,20 +80,20 @@ return [
|
||||
'default' => 'Bawaan',
|
||||
'breadcrumb' => 'Breadcrumb',
|
||||
'status' => 'Status',
|
||||
'status_active' => 'Active',
|
||||
'status_inactive' => 'Inactive',
|
||||
'never' => 'Never',
|
||||
'none' => 'None',
|
||||
'status_active' => 'Aktif',
|
||||
'status_inactive' => 'Tidak Aktif',
|
||||
'never' => 'Jangan Pernah',
|
||||
'none' => 'Tidak Satupun',
|
||||
|
||||
// Header
|
||||
'homepage' => 'Homepage',
|
||||
'homepage' => 'Beranda',
|
||||
'header_menu_expand' => 'Perluas Menu Tajuk',
|
||||
'profile_menu' => 'Menu Profil',
|
||||
'view_profile' => 'Tampilkan Profil',
|
||||
'edit_profile' => 'Sunting Profil',
|
||||
'dark_mode' => 'Mode Gelap',
|
||||
'light_mode' => 'Mode Terang',
|
||||
'global_search' => 'Global Search',
|
||||
'global_search' => 'Pencarian Global',
|
||||
|
||||
// Layout tabs
|
||||
'tab_info' => 'Informasi',
|
||||
@@ -111,5 +111,5 @@ return [
|
||||
'terms_of_service' => 'Ketentuan Layanan',
|
||||
|
||||
// OpenSearch
|
||||
'opensearch_description' => 'Search :appName',
|
||||
'opensearch_description' => 'Cari :appName',
|
||||
];
|
||||
|
@@ -6,36 +6,36 @@ return [
|
||||
|
||||
// Image Manager
|
||||
'image_select' => 'Pilih Gambar',
|
||||
'image_list' => 'Image List',
|
||||
'image_details' => 'Image Details',
|
||||
'image_upload' => 'Upload Image',
|
||||
'image_intro' => 'Here you can select and manage images that have been previously uploaded to the system.',
|
||||
'image_intro_upload' => 'Upload a new image by dragging an image file into this window, or by using the "Upload Image" button above.',
|
||||
'image_list' => 'Daftar Gambar',
|
||||
'image_details' => 'Detail Gambar',
|
||||
'image_upload' => 'Unggah Gambar',
|
||||
'image_intro' => 'Di sini Anda dapat memilih dan mengelola gambar yang sebelumnya diunggah ke sistem.',
|
||||
'image_intro_upload' => 'Unggah gambar baru dengan menyeret berkas gambar ke jendela ini, atau dengan menggunakan tombol "Unggah Gambar" di atas.',
|
||||
'image_all' => 'Semua',
|
||||
'image_all_title' => 'Lihat semua gambar',
|
||||
'image_book_title' => 'Lihat gambar yang diunggah ke buku ini',
|
||||
'image_page_title' => 'Lihat gambar yang diunggah ke halaman ini',
|
||||
'image_search_hint' => 'Cari berdasarkan nama gambar',
|
||||
'image_uploaded' => 'Diunggah :uploadedDate',
|
||||
'image_uploaded_by' => 'Uploaded by :userName',
|
||||
'image_uploaded_to' => 'Uploaded to :pageLink',
|
||||
'image_updated' => 'Updated :updateDate',
|
||||
'image_uploaded_by' => 'Diunggah oleh :userName',
|
||||
'image_uploaded_to' => 'Diunggah ke :pageLink',
|
||||
'image_updated' => 'Diperbarui :updateDate',
|
||||
'image_load_more' => 'Muat lebih banyak',
|
||||
'image_image_name' => 'Muat lebih banyak',
|
||||
'image_delete_used' => 'Gambar ini digunakan untuk halaman dibawah ini.',
|
||||
'image_delete_confirm_text' => 'Anda yakin ingin menghapus gambar ini?',
|
||||
'image_select_image' => 'Pilih gambar',
|
||||
'image_dropzone' => 'Lepaskan gambar atau klik di sini untuk mengunggah',
|
||||
'image_dropzone_drop' => 'Drop images here to upload',
|
||||
'image_dropzone_drop' => 'Letakkan gambar di sini untuk diunggah',
|
||||
'images_deleted' => 'Gambar Dihapus',
|
||||
'image_preview' => 'Pratinjau Gambar',
|
||||
'image_upload_success' => 'Gambar berhasil diunggah',
|
||||
'image_update_success' => 'Detail gambar berhasil diperbarui',
|
||||
'image_delete_success' => 'Gambar berhasil dihapus',
|
||||
'image_replace' => 'Replace Image',
|
||||
'image_replace_success' => 'Image file successfully updated',
|
||||
'image_rebuild_thumbs' => 'Regenerate Size Variations',
|
||||
'image_rebuild_thumbs_success' => 'Image size variations successfully rebuilt!',
|
||||
'image_replace' => 'Ganti Gambar',
|
||||
'image_replace_success' => 'Berkas gambar berhasil diperbarui',
|
||||
'image_rebuild_thumbs' => 'Buat Ulang Variasi Ukuran',
|
||||
'image_rebuild_thumbs_success' => 'Variasi ukuran gambar berhasil dibuat ulang!',
|
||||
|
||||
// Code Editor
|
||||
'code_editor' => 'Edit Kode',
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user