LDAP_ID_ATTRIBUTE=uid
LDAP_EMAIL_ATTRIBUTE=mail
LDAP_DISPLAY_NAME_ATTRIBUTE=cn
+LDAP_THUMBNAIL_ATTRIBUTE=null
LDAP_FOLLOW_REFERRALS=true
LDAP_DUMP_USER_DETAILS=false
SAML2_ONELOGIN_OVERRIDES=null
SAML2_DUMP_USER_DETAILS=false
SAML2_AUTOLOAD_METADATA=false
+SAML2_IDP_AUTHNCONTEXT=true
# SAML group sync configuration
# Refer to https://www.bookstackapp.com/docs/admin/saml2-auth/
@benediktvolke :: German
@Baptistou :: French
@arcoai :: Spanish
+@Jokuna :: Korean
cipi1965 :: Italian
Mykola Ronik (Mantikor) :: Ukrainian
furkanoyk :: Turkish
HenrijsS :: Latvian
Pascal R-B (pborgner) :: German
Boris (Ginfred) :: Russian
+Jonas Anker Rasmussen (jonasanker) :: Danish
+Gerwin de Keijzer (gdekeijzer) :: Dutch; German; German Informal
+kometchtech :: Japanese
+Auri (Atalonica) :: Catalan
+Francesco Franchina (ffranchina) :: Italian
+Aimrane Kds (aimrane.kds) :: Arabic
+whenwesober :: Indonesian
+Rem (remkovdhoef) :: Dutch
+syn7ax69 :: Bulgarian; Turkish
+Blaade :: French
--- /dev/null
+<?php namespace BookStack\Actions;
+
+use BookStack\Model;
+use Illuminate\Database\Eloquent\Relations\MorphTo;
+
+class Favourite extends Model
+{
+ protected $fillable = ['user_id'];
+
+ /**
+ * Get the related model that can be favourited.
+ */
+ public function favouritable(): MorphTo
+ {
+ return $this->morphTo();
+ }
+}
<?php namespace BookStack\Actions;
use BookStack\Model;
+use Illuminate\Database\Eloquent\Relations\MorphTo;
class Tag extends Model
{
/**
* Get the entity that this tag belongs to
- * @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
- public function entity()
+ public function entity(): MorphTo
{
return $this->morphTo('entity');
}
+
+ /**
+ * Get a full URL to start a tag name search for this tag name.
+ */
+ public function nameUrl(): string
+ {
+ return url('/search?term=%5B' . urlencode($this->name) .'%5D');
+ }
+
+ /**
+ * Get a full URL to start a tag name and value search for this tag's values.
+ */
+ public function valueUrl(): string
+ {
+ return url('/search?term=%5B' . urlencode($this->name) .'%3D' . urlencode($this->value) . '%5D');
+ }
}
<?php namespace BookStack\Actions;
+use BookStack\Interfaces\Viewable;
use BookStack\Model;
+use Illuminate\Database\Eloquent\Relations\MorphTo;
+/**
+ * Class View
+ * Views are stored per-item per-person within the database.
+ * They can be used to find popular items or recently viewed items
+ * at a per-person level. They do not record every view instance as an
+ * activity. Only the latest and original view times could be recognised.
+ *
+ * @property int $views
+ * @property int $user_id
+ */
class View extends Model
{
/**
* Get all owning viewable models.
- * @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
- public function viewable()
+ public function viewable(): MorphTo
{
return $this->morphTo();
}
+
+ /**
+ * Increment the current user's view count for the given viewable model.
+ */
+ public static function incrementFor(Viewable $viewable): int
+ {
+ $user = user();
+ if (is_null($user) || $user->isDefault()) {
+ return 0;
+ }
+
+ /** @var View $view */
+ $view = $viewable->views()->firstOrNew([
+ 'user_id' => $user->id,
+ ], ['views' => 0]);
+
+ $view->forceFill(['views' => $view->views + 1])->save();
+
+ return $view->views;
+ }
+
+ /**
+ * Clear all views from the system.
+ */
+ public static function clearAll()
+ {
+ static::query()->truncate();
+ }
}
+++ /dev/null
-<?php namespace BookStack\Actions;
-
-use BookStack\Auth\Permissions\PermissionService;
-use BookStack\Entities\Models\Book;
-use BookStack\Entities\Models\Entity;
-use BookStack\Entities\EntityProvider;
-use DB;
-use Illuminate\Support\Collection;
-
-class ViewService
-{
- protected $view;
- protected $permissionService;
- protected $entityProvider;
-
- /**
- * ViewService constructor.
- * @param View $view
- * @param PermissionService $permissionService
- * @param EntityProvider $entityProvider
- */
- public function __construct(View $view, PermissionService $permissionService, EntityProvider $entityProvider)
- {
- $this->view = $view;
- $this->permissionService = $permissionService;
- $this->entityProvider = $entityProvider;
- }
-
- /**
- * Add a view to the given entity.
- * @param \BookStack\Entities\Models\Entity $entity
- * @return int
- */
- public function add(Entity $entity)
- {
- $user = user();
- if ($user === null || $user->isDefault()) {
- return 0;
- }
- $view = $entity->views()->where('user_id', '=', $user->id)->first();
- // Add view if model exists
- if ($view) {
- $view->increment('views');
- return $view->views;
- }
-
- // Otherwise create new view count
- $entity->views()->save($this->view->newInstance([
- 'user_id' => $user->id,
- 'views' => 1
- ]));
-
- return 1;
- }
-
- /**
- * Get the entities with the most views.
- * @param int $count
- * @param int $page
- * @param string|array $filterModels
- * @param string $action - used for permission checking
- * @return Collection
- */
- public function getPopular(int $count = 10, int $page = 0, array $filterModels = null, string $action = 'view')
- {
- $skipCount = $count * $page;
- $query = $this->permissionService
- ->filterRestrictedEntityRelations($this->view->newQuery(), 'views', 'viewable_id', 'viewable_type', $action)
- ->select('*', 'viewable_id', 'viewable_type', DB::raw('SUM(views) as view_count'))
- ->groupBy('viewable_id', 'viewable_type')
- ->orderBy('view_count', 'desc');
-
- if ($filterModels) {
- $query->whereIn('viewable_type', $this->entityProvider->getMorphClasses($filterModels));
- }
-
- return $query->with('viewable')
- ->skip($skipCount)
- ->take($count)
- ->get()
- ->pluck('viewable')
- ->filter();
- }
-
- /**
- * Get all recently viewed entities for the current user.
- */
- public function getUserRecentlyViewed(int $count = 10, int $page = 1)
- {
- $user = user();
- if ($user === null || $user->isDefault()) {
- return collect();
- }
-
- $all = collect();
- /** @var Entity $instance */
- foreach ($this->entityProvider->all() as $name => $instance) {
- $items = $instance::visible()->withLastView()
- ->orderBy('last_viewed_at', 'desc')
- ->skip($count * ($page - 1))
- ->take($count)
- ->get();
- $all = $all->concat($items);
- }
-
- return $all->sortByDesc('last_viewed_at')->slice(0, $count);
- }
-
- /**
- * Reset all view counts by deleting all views.
- */
- public function resetAll()
- {
- $this->view->truncate();
- }
-}
$this->ldapService->syncGroups($user, $username);
}
+ // Attach avatar if non-existent
+ if (is_null($user->avatar)) {
+ $this->ldapService->saveAndAttachAvatar($user, $userDetails);
+ }
+
$this->login($user, $remember);
return true;
}
'password' => Str::random(32),
];
- return $this->registrationService->registerUser($details, null, false);
+ $user = $this->registrationService->registerUser($details, null, false);
+ $this->ldapService->saveAndAttachAvatar($user, $ldapUserDetails);
+ return $user;
}
}
use BookStack\Auth\User;
use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\LdapException;
+use BookStack\Uploads\UserAvatars;
use ErrorException;
+use Illuminate\Support\Facades\Log;
/**
* Class LdapService
protected $ldap;
protected $ldapConnection;
+ protected $userAvatars;
protected $config;
protected $enabled;
/**
* LdapService constructor.
*/
- public function __construct(Ldap $ldap)
+ public function __construct(Ldap $ldap, UserAvatars $userAvatars)
{
$this->ldap = $ldap;
+ $this->userAvatars = $userAvatars;
$this->config = config('services.ldap');
$this->enabled = config('auth.method') === 'ldap';
}
$idAttr = $this->config['id_attribute'];
$emailAttr = $this->config['email_attribute'];
$displayNameAttr = $this->config['display_name_attribute'];
+ $thumbnailAttr = $this->config['thumbnail_attribute'];
- $user = $this->getUserWithAttributes($userName, ['cn', 'dn', $idAttr, $emailAttr, $displayNameAttr]);
+ $user = $this->getUserWithAttributes($userName, array_filter([
+ 'cn', 'dn', $idAttr, $emailAttr, $displayNameAttr, $thumbnailAttr,
+ ]));
- if ($user === null) {
+ if (is_null($user)) {
return null;
}
'name' => $this->getUserResponseProperty($user, $displayNameAttr, $userCn),
'dn' => $user['dn'],
'email' => $this->getUserResponseProperty($user, $emailAttr, null),
+ 'avatar'=> $thumbnailAttr ? $this->getUserResponseProperty($user, $thumbnailAttr, null) : null,
];
if ($this->config['dump_user_details']) {
$userLdapGroups = $this->getUserGroups($username);
$this->syncWithGroups($user, $userLdapGroups);
}
+
+ /**
+ * Save and attach an avatar image, if found in the ldap details, and attach
+ * to the given user model.
+ */
+ public function saveAndAttachAvatar(User $user, array $ldapUserDetails): void
+ {
+ if (is_null(config('services.ldap.thumbnail_attribute')) || is_null($ldapUserDetails['avatar'])) {
+ return;
+ }
+
+ try {
+ $imageData = $ldapUserDetails['avatar'];
+ $this->userAvatars->assignToUserFromExistingData($user, $imageData, 'jpg');
+ } catch (\Exception $exception) {
+ Log::info("Failed to use avatar image from LDAP data for user id {$user->id}");
+ }
+ }
}
class SocialAuthService
{
+ /**
+ * The core socialite library used.
+ * @var Socialite
+ */
protected $socialite;
- protected $socialAccount;
- protected $validSocialDrivers = ['google', 'github', 'facebook', 'slack', 'twitter', 'azure', 'okta', 'gitlab', 'twitch', 'discord'];
+ /**
+ * The default built-in social drivers we support.
+ * @var string[]
+ */
+ protected $validSocialDrivers = [
+ 'google',
+ 'github',
+ 'facebook',
+ 'slack',
+ 'twitter',
+ 'azure',
+ 'okta',
+ 'gitlab',
+ 'twitch',
+ 'discord'
+ ];
+
+ /**
+ * Callbacks to run when configuring a social driver
+ * for an initial redirect action.
+ * Array is keyed by social driver name.
+ * Callbacks are passed an instance of the driver.
+ * @var array<string, callable>
+ */
+ protected $configureForRedirectCallbacks = [];
/**
* SocialAuthService constructor.
public function startLogIn(string $socialDriver): RedirectResponse
{
$driver = $this->validateDriver($socialDriver);
- return $this->getSocialDriver($driver)->redirect();
+ return $this->getDriverForRedirect($driver)->redirect();
}
/**
public function startRegister(string $socialDriver): RedirectResponse
{
$driver = $this->validateDriver($socialDriver);
- return $this->getSocialDriver($driver)->redirect();
+ return $this->getDriverForRedirect($driver)->redirect();
}
/**
/**
* Provide redirect options per service for the Laravel Socialite driver
*/
- public function getSocialDriver(string $driverName): Provider
+ protected function getDriverForRedirect(string $driverName): Provider
{
$driver = $this->socialite->driver($driverName);
$driver->with(['resource' => 'https://graph.windows.net']);
}
+ if (isset($this->configureForRedirectCallbacks[$driverName])) {
+ $this->configureForRedirectCallbacks[$driverName]($driver);
+ }
+
return $driver;
}
* within the `Config/services.php` file.
* Handler should be a Class@method handler to the SocialiteWasCalled event.
*/
- public function addSocialDriver(string $driverName, array $config, string $socialiteHandler)
- {
+ public function addSocialDriver(
+ string $driverName,
+ array $config,
+ string $socialiteHandler,
+ callable $configureForRedirect = null
+ ) {
$this->validSocialDrivers[] = $driverName;
config()->set('services.' . $driverName, $config);
config()->set('services.' . $driverName . '.redirect', url('/login/service/' . $driverName . '/callback'));
config()->set('services.' . $driverName . '.name', $config['name'] ?? $driverName);
Event::listen(SocialiteWasCalled::class, $socialiteHandler);
+ if (!is_null($configureForRedirect)) {
+ $this->configureForRedirectCallbacks[$driverName] = $configureForRedirect;
+ }
}
}
/**
* Filter items that have entities set as a polymorphic relation.
+ * @param Builder|\Illuminate\Database\Query\Builder $query
*/
- public function filterRestrictedEntityRelations(Builder $query, string $tableName, string $entityIdColumn, string $entityTypeColumn, string $action = 'view'): Builder
+ public function filterRestrictedEntityRelations($query, string $tableName, string $entityIdColumn, string $entityTypeColumn, string $action = 'view')
{
$tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn];
$q = $query->where(function ($query) use ($tableDetails, $action) {
$query->whereExists(function ($permissionQuery) use (&$tableDetails, $action) {
- $permissionQuery->select('id')->from('joint_permissions')
+ $permissionQuery->select(['role_id'])->from('joint_permissions')
->whereRaw('joint_permissions.entity_id=' . $tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn'])
->whereRaw('joint_permissions.entity_type=' . $tableDetails['tableName'] . '.' . $tableDetails['entityTypeColumn'])
->where('action', '=', $action)
}
/**
- * Get all visible roles
+ * Get all visible roles.
*/
public static function visible(): Collection
{
*/
public static function restrictable(): Collection
{
- return static::query()->where('system_name', '!=', 'admin')->get();
+ return static::query()
+ ->where('system_name', '!=', 'admin')
+ ->orderBy('display_name', 'asc')
+ ->get();
}
/**
<?php namespace BookStack\Auth;
+use BookStack\Actions\Favourite;
use BookStack\Api\ApiToken;
use BookStack\Entities\Tools\SlugGenerator;
use BookStack\Interfaces\Loggable;
return $this->hasMany(ApiToken::class);
}
+ /**
+ * Get the favourite instances for this user.
+ */
+ public function favourites(): HasMany
+ {
+ return $this->hasMany(Favourite::class);
+ }
+
/**
* Get the last activity time for this user.
*/
use BookStack\Entities\Models\Page;
use BookStack\Exceptions\NotFoundException;
use BookStack\Exceptions\UserUpdateException;
-use BookStack\Uploads\Image;
use BookStack\Uploads\UserAvatars;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
-use Images;
use Log;
class UserRepo
{
$user->socialAccounts()->delete();
$user->apiTokens()->delete();
+ $user->favourites()->delete();
$user->delete();
// Delete user profile images
- $profileImages = Image::query()->where('type', '=', 'user')
- ->where('uploaded_to', '=', $user->id)
- ->get();
-
- foreach ($profileImages as $image) {
- Images::destroy($image);
- }
+ $this->userAvatar->destroyAllForUser($user);
if (!empty($newOwnerId)) {
$newOwner = User::query()->find($newOwnerId);
'locale' => env('APP_LANG', 'en'),
// Locales available
- 'locales' => ['en', 'ar', 'bg', 'bs', 'ca', 'cs', 'da', 'de', 'de_informal', 'es', 'es_AR', 'fa', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'ko', 'lv', 'nl', 'nb', 'pt', 'pt_BR', 'sk', 'sl', 'sv', 'pl', 'ru', 'th', 'tr', 'uk', 'vi', 'zh_CN', 'zh_TW',],
+ 'locales' => ['en', 'ar', 'bg', 'bs', 'ca', 'cs', 'da', 'de', 'de_informal', 'es', 'es_AR', 'fa', 'fr', 'he', 'hr', 'hu', 'id', 'it', 'ja', 'ko', 'lv', 'nl', 'nb', 'pt', 'pt_BR', 'sk', 'sl', 'sv', 'pl', 'ru', 'th', 'tr', 'uk', 'vi', 'zh_CN', 'zh_TW',],
// Application Fallback Locale
'fallback_locale' => 'en',
// Custom BookStack
'Activity' => BookStack\Facades\Activity::class,
- 'Views' => BookStack\Facades\Views::class,
- 'Images' => BookStack\Facades\Images::class,
'Permissions' => BookStack\Facades\Permissions::class,
'Theme' => BookStack\Facades\Theme::class,
-
],
// Proxy configuration
* Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
* Symbol, ZapfDingbats.
*/
- "DOMPDF_FONT_DIR" => app_path('vendor/dompdf/dompdf/lib/fonts/'), //storage_path('fonts/'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
+ "DOMPDF_FONT_DIR" => storage_path('fonts/'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
/**
* The location of the DOMPDF font cache directory
*
* @var bool
*/
- "DOMPDF_ENABLE_JAVASCRIPT" => true,
+ "DOMPDF_ENABLE_JAVASCRIPT" => false,
/**
* Enable remote file access
<?php
+$SAML2_IDP_AUTHNCONTEXT = env('SAML2_IDP_AUTHNCONTEXT', true);
+
return [
// Display name, shown to users, for SAML2 option
// )
// ),
],
+ 'security' => [
+ // SAML2 Authn context
+ // When set to false no AuthContext will be sent in the AuthNRequest,
+ // When set to true (Default) you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'.
+ // Multiple forced values can be passed via a space separated array, For example:
+ // SAML2_IDP_AUTHNCONTEXT="urn:federation:authentication:windows urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
+ 'requestedAuthnContext' => is_string($SAML2_IDP_AUTHNCONTEXT) ? explode(' ', $SAML2_IDP_AUTHNCONTEXT) : $SAML2_IDP_AUTHNCONTEXT,
+ ],
],
];
'remove_from_groups' => env('LDAP_REMOVE_FROM_GROUPS', false),
'tls_insecure' => env('LDAP_TLS_INSECURE', false),
'start_tls' => env('LDAP_START_TLS', false),
+ 'thumbnail_attribute' => env('LDAP_THUMBNAIL_ATTRIBUTE', null),
],
];
namespace BookStack\Console\Commands;
+use BookStack\Actions\View;
use Illuminate\Console\Command;
class ClearViews extends Command
*/
public function handle()
{
- \Views::resetAll();
+ View::clearAll();
$this->comment('Views cleared');
}
}
/**
* Class Chapter
* @property Collection<Page> $pages
+ * @property mixed description
*/
class Chapter extends BookChild
{
use BookStack\Actions\Activity;
use BookStack\Actions\Comment;
+use BookStack\Actions\Favourite;
use BookStack\Actions\Tag;
use BookStack\Actions\View;
use BookStack\Auth\Permissions\EntityPermission;
use BookStack\Entities\Tools\SearchIndex;
use BookStack\Entities\Tools\SlugGenerator;
use BookStack\Facades\Permissions;
+use BookStack\Interfaces\Favouritable;
use BookStack\Interfaces\Sluggable;
+use BookStack\Interfaces\Viewable;
use BookStack\Model;
use BookStack\Traits\HasCreatorAndUpdater;
use BookStack\Traits\HasOwner;
* @method static Builder withLastView()
* @method static Builder withViewCount()
*/
-abstract class Entity extends Model implements Sluggable
+abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
{
use SoftDeletes;
use HasCreatorAndUpdater;
$this->slug = app(SlugGenerator::class)->generate($this);
return $this->slug;
}
+
+ /**
+ * @inheritdoc
+ */
+ public function favourites(): MorphMany
+ {
+ return $this->morphMany(Favourite::class, 'favouritable');
+ }
+
+ /**
+ * Check if the entity is a favourite of the current user.
+ */
+ public function isFavourite(): bool
+ {
+ return $this->favourites()
+ ->where('user_id', '=', user()->id)
+ ->exists();
+ }
}
/**
* Get the associated page revisions, ordered by created date.
- * @return mixed
+ * Only provides actual saved page revision instances, Not drafts.
+ */
+ public function revisions(): HasMany
+ {
+ return $this->allRevisions()
+ ->where('type', '=', 'version')
+ ->orderBy('created_at', 'desc')
+ ->orderBy('id', 'desc');
+ }
+
+ /**
+ * Get all revision instances assigned to this page.
+ * Includes all types of revisions.
*/
- public function revisions()
+ public function allRevisions(): HasMany
{
- return $this->hasMany(PageRevision::class)->where('type', '=', 'version')->orderBy('created_at', 'desc')->orderBy('id', 'desc');
+ return $this->hasMany(PageRevision::class);
}
/**
--- /dev/null
+<?php namespace BookStack\Entities\Queries;
+
+use BookStack\Auth\Permissions\PermissionService;
+use BookStack\Entities\EntityProvider;
+
+abstract class EntityQuery
+{
+ protected function permissionService(): PermissionService
+ {
+ return app()->make(PermissionService::class);
+ }
+
+ protected function entityProvider(): EntityProvider
+ {
+ return app()->make(EntityProvider::class);
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php namespace BookStack\Entities\Queries;
+
+
+use BookStack\Actions\View;
+use Illuminate\Support\Facades\DB;
+
+class Popular extends EntityQuery
+{
+ public function run(int $count, int $page, array $filterModels = null, string $action = 'view')
+ {
+ $query = $this->permissionService()
+ ->filterRestrictedEntityRelations(View::query(), 'views', 'viewable_id', 'viewable_type', $action)
+ ->select('*', 'viewable_id', 'viewable_type', DB::raw('SUM(views) as view_count'))
+ ->groupBy('viewable_id', 'viewable_type')
+ ->orderBy('view_count', 'desc');
+
+ if ($filterModels) {
+ $query->whereIn('viewable_type', $this->entityProvider()->getMorphClasses($filterModels));
+ }
+
+ return $query->with('viewable')
+ ->skip($count * ($page - 1))
+ ->take($count)
+ ->get()
+ ->pluck('viewable')
+ ->filter();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php namespace BookStack\Entities\Queries;
+
+use BookStack\Actions\View;
+use Illuminate\Support\Collection;
+
+class RecentlyViewed extends EntityQuery
+{
+ public function run(int $count, int $page): Collection
+ {
+ $user = user();
+ if ($user === null || $user->isDefault()) {
+ return collect();
+ }
+
+ $query = $this->permissionService()->filterRestrictedEntityRelations(
+ View::query(),
+ 'views',
+ 'viewable_id',
+ 'viewable_type',
+ 'view'
+ )
+ ->orderBy('views.updated_at', 'desc')
+ ->where('user_id', '=', user()->id);
+
+ return $query->with('viewable')
+ ->skip(($page - 1) * $count)
+ ->take($count)
+ ->get()
+ ->pluck('viewable')
+ ->filter();
+ }
+}
--- /dev/null
+<?php namespace BookStack\Entities\Queries;
+
+use BookStack\Actions\Favourite;
+use Illuminate\Database\Query\JoinClause;
+
+class TopFavourites extends EntityQuery
+{
+ public function run(int $count, int $skip = 0)
+ {
+ $user = user();
+ if (is_null($user) || $user->isDefault()) {
+ return collect();
+ }
+
+ $query = $this->permissionService()
+ ->filterRestrictedEntityRelations(Favourite::query(), 'favourites', 'favouritable_id', 'favouritable_type', 'view')
+ ->select('favourites.*')
+ ->leftJoin('views', function (JoinClause $join) {
+ $join->on('favourites.favouritable_id', '=', 'views.viewable_id');
+ $join->on('favourites.favouritable_type', '=', 'views.viewable_type');
+ $join->where('views.user_id', '=', user()->id);
+ })
+ ->orderBy('views.views', 'desc')
+ ->where('favourites.user_id', '=', user()->id);
+
+ return $query->with('favouritable')
+ ->skip($skip)
+ ->take($count)
+ ->get()
+ ->pluck('favouritable')
+ ->filter();
+ }
+}
if (!empty($input['markdown'] ?? '')) {
$pageContent->setNewMarkdown($input['markdown']);
} else {
- $pageContent->setNewHTML($input['html']);
+ $pageContent->setNewHTML($input['html'] ?? '');
}
}
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Page;
+use BookStack\Entities\Tools\Markdown\HtmlToMarkdown;
use BookStack\Uploads\ImageService;
use DomPDF;
use Exception;
}
return $text;
}
+
+ /**
+ * Convert a page to a Markdown file.
+ */
+ public function pageToMarkdown(Page $page): string
+ {
+ if ($page->markdown) {
+ return "# " . $page->name . "\n\n" . $page->markdown;
+ }
+
+ return "# " . $page->name . "\n\n" . (new HtmlToMarkdown($page->html))->convert();
+ }
+
+ /**
+ * Convert a chapter to a Markdown file.
+ */
+ public function chapterToMarkdown(Chapter $chapter): string
+ {
+ $text = "# " . $chapter->name . "\n\n";
+ $text .= $chapter->description . "\n\n";
+ foreach ($chapter->pages as $page) {
+ $text .= $this->pageToMarkdown($page) . "\n\n";
+ }
+ return $text;
+ }
+
+ /**
+ * Convert a book into a plain text string.
+ */
+ public function bookToMarkdown(Book $book): string
+ {
+ $bookTree = (new BookContents($book))->getTree(false, true);
+ $text = "# " . $book->name . "\n\n";
+ foreach ($bookTree as $bookChild) {
+ if ($bookChild instanceof Chapter) {
+ $text .= $this->chapterToMarkdown($bookChild);
+ } else {
+ $text .= $this->pageToMarkdown($bookChild);
+ }
+ }
+ return $text;
+ }
}
--- /dev/null
+<?php namespace BookStack\Entities\Tools\Markdown;
+
+use League\HTMLToMarkdown\Converter\ParagraphConverter;
+use League\HTMLToMarkdown\ElementInterface;
+
+class CustomParagraphConverter extends ParagraphConverter
+{
+ public function convert(ElementInterface $element): string
+ {
+ $class = $element->getAttribute('class');
+ if (strpos($class, 'callout') !== false) {
+ return "<{$element->getTagName()} class=\"{$class}\">{$element->getValue()}</{$element->getTagName()}>\n\n";
+ }
+
+ return parent::convert($element);
+ }
+}
--- /dev/null
+<?php namespace BookStack\Entities\Tools\Markdown;
+
+use League\HTMLToMarkdown\Converter\BlockquoteConverter;
+use League\HTMLToMarkdown\Converter\CodeConverter;
+use League\HTMLToMarkdown\Converter\CommentConverter;
+use League\HTMLToMarkdown\Converter\DivConverter;
+use League\HTMLToMarkdown\Converter\EmphasisConverter;
+use League\HTMLToMarkdown\Converter\HardBreakConverter;
+use League\HTMLToMarkdown\Converter\HeaderConverter;
+use League\HTMLToMarkdown\Converter\HorizontalRuleConverter;
+use League\HTMLToMarkdown\Converter\ImageConverter;
+use League\HTMLToMarkdown\Converter\LinkConverter;
+use League\HTMLToMarkdown\Converter\ListBlockConverter;
+use League\HTMLToMarkdown\Converter\ListItemConverter;
+use League\HTMLToMarkdown\Converter\PreformattedConverter;
+use League\HTMLToMarkdown\Converter\TextConverter;
+use League\HTMLToMarkdown\Environment;
+use League\HTMLToMarkdown\HtmlConverter;
+
+class HtmlToMarkdown
+{
+ protected $html;
+
+ public function __construct(string $html)
+ {
+ $this->html = $html;
+ }
+
+ /**
+ * Run the conversion
+ */
+ public function convert(): string
+ {
+ $converter = new HtmlConverter($this->getConverterEnvironment());
+ $html = $this->prepareHtml($this->html);
+ return $converter->convert($html);
+ }
+
+ /**
+ * Run any pre-processing to the HTML to clean it up manually before conversion.
+ */
+ protected function prepareHtml(string $html): string
+ {
+ // Carriage returns can cause whitespace issues in output
+ $html = str_replace("\r\n", "\n", $html);
+ // Attributes on the pre tag can cause issues with conversion
+ return preg_replace('/<pre .*?>/', '<pre>', $html);
+ }
+
+ /**
+ * Get the HTML to Markdown customized environment.
+ * Extends the default provided environment with some BookStack specific tweaks.
+ */
+ protected function getConverterEnvironment(): Environment
+ {
+ $environment = new Environment([
+ 'header_style' => 'atx', // Set to 'atx' to output H1 and H2 headers as # Header1 and ## Header2
+ 'suppress_errors' => true, // Set to false to show warnings when loading malformed HTML
+ 'strip_tags' => false, // Set to true to strip tags that don't have markdown equivalents. N.B. Strips tags, not their content. Useful to clean MS Word HTML output.
+ 'strip_placeholder_links' => false, // Set to true to remove <a> that doesn't have href.
+ 'bold_style' => '**', // DEPRECATED: Set to '__' if you prefer the underlined style
+ 'italic_style' => '*', // DEPRECATED: Set to '_' if you prefer the underlined style
+ 'remove_nodes' => '', // space-separated list of dom nodes that should be removed. example: 'meta style script'
+ 'hard_break' => false, // Set to true to turn <br> into `\n` instead of ` \n`
+ 'list_item_style' => '-', // Set the default character for each <li> in a <ul>. Can be '-', '*', or '+'
+ 'preserve_comments' => false, // Set to true to preserve comments, or set to an array of strings to preserve specific comments
+ 'use_autolinks' => false, // Set to true to use simple link syntax if possible. Will always use []() if set to false
+ 'table_pipe_escape' => '\|', // Replacement string for pipe characters inside markdown table cells
+ 'table_caption_side' => 'top', // Set to 'top' or 'bottom' to show <caption> content before or after table, null to suppress
+ ]);
+
+ $environment->addConverter(new BlockquoteConverter());
+ $environment->addConverter(new CodeConverter());
+ $environment->addConverter(new CommentConverter());
+ $environment->addConverter(new DivConverter());
+ $environment->addConverter(new EmphasisConverter());
+ $environment->addConverter(new HardBreakConverter());
+ $environment->addConverter(new HeaderConverter());
+ $environment->addConverter(new HorizontalRuleConverter());
+ $environment->addConverter(new ImageConverter());
+ $environment->addConverter(new LinkConverter());
+ $environment->addConverter(new ListBlockConverter());
+ $environment->addConverter(new ListItemConverter());
+ $environment->addConverter(new CustomParagraphConverter());
+ $environment->addConverter(new PreformattedConverter());
+ $environment->addConverter(new TextConverter());
+
+ return $environment;
+ }
+}
--- /dev/null
+<?php namespace BookStack\Entities\Tools;
+
+use BookStack\Entities\Models\BookChild;
+use BookStack\Entities\Models\Entity;
+use Illuminate\Support\Collection;
+
+/**
+ * Finds the next or previous content of a book element (page or chapter).
+ */
+class NextPreviousContentLocator
+{
+ protected $relativeBookItem;
+ protected $flatTree;
+ protected $currentIndex = null;
+
+ /**
+ * NextPreviousContentLocator constructor.
+ */
+ public function __construct(BookChild $relativeBookItem, Collection $bookTree)
+ {
+ $this->relativeBookItem = $relativeBookItem;
+ $this->flatTree = $this->treeToFlatOrderedCollection($bookTree);
+ $this->currentIndex = $this->getCurrentIndex();
+ }
+
+ /**
+ * Get the next logical entity within the book hierarchy.
+ */
+ public function getNext(): ?Entity
+ {
+ return $this->flatTree->get($this->currentIndex + 1);
+ }
+
+ /**
+ * Get the next logical entity within the book hierarchy.
+ */
+ public function getPrevious(): ?Entity
+ {
+ return $this->flatTree->get($this->currentIndex - 1);
+ }
+
+ /**
+ * Get the index of the current relative item.
+ */
+ protected function getCurrentIndex(): ?int
+ {
+ $index = $this->flatTree->search(function (Entity $entity) {
+ return get_class($entity) === get_class($this->relativeBookItem)
+ && $entity->id === $this->relativeBookItem->id;
+ });
+ return $index === false ? null : $index;
+ }
+
+ /**
+ * Convert a book tree collection to a flattened version
+ * where all items follow the expected order of user flow.
+ */
+ protected function treeToFlatOrderedCollection(Collection $bookTree): Collection
+ {
+ $flatOrdered = collect();
+ /** @var Entity $item */
+ foreach ($bookTree->all() as $item) {
+ $flatOrdered->push($item);
+ $childPages = $item->visible_pages ?? [];
+ $flatOrdered = $flatOrdered->concat($childPages);
+ }
+ return $flatOrdered;
+ }
+}
use BookStack\Entities\Models\Page;
use BookStack\Entities\Tools\Markdown\CustomStrikeThroughExtension;
+use BookStack\Exceptions\ImageUploadException;
use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents;
+use BookStack\Util\HtmlContentFilter;
+use BookStack\Uploads\ImageRepo;
use DOMDocument;
use DOMNodeList;
use DOMXPath;
+use Illuminate\Support\Str;
use League\CommonMark\CommonMarkConverter;
use League\CommonMark\Environment;
use League\CommonMark\Extension\Table\TableExtension;
*/
public function setNewHTML(string $html)
{
+ $html = $this->extractBase64Images($this->page, $html);
$this->page->html = $this->formatHtml($html);
$this->page->text = $this->toPlainText();
$this->page->markdown = '';
return $converter->convertToHtml($markdown);
}
+ /**
+ * Convert all base64 image data to saved images
+ */
+ public function extractBase64Images(Page $page, string $htmlText): string
+ {
+ if (empty($htmlText) || strpos($htmlText, 'data:image') === false) {
+ return $htmlText;
+ }
+
+ $doc = $this->loadDocumentFromHtml($htmlText);
+ $container = $doc->documentElement;
+ $body = $container->childNodes->item(0);
+ $childNodes = $body->childNodes;
+ $xPath = new DOMXPath($doc);
+ $imageRepo = app()->make(ImageRepo::class);
+ $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
+
+ // Get all img elements with image data blobs
+ $imageNodes = $xPath->query('//img[contains(@src, \'data:image\')]');
+ foreach ($imageNodes as $imageNode) {
+ $imageSrc = $imageNode->getAttribute('src');
+ [$dataDefinition, $base64ImageData] = explode(',', $imageSrc, 2);
+ $extension = strtolower(preg_split('/[\/;]/', $dataDefinition)[1] ?? 'png');
+
+ // Validate extension
+ if (!in_array($extension, $allowedExtensions)) {
+ $imageNode->setAttribute('src', '');
+ continue;
+ }
+
+ // Save image from data with a random name
+ $imageName = 'embedded-image-' . Str::random(8) . '.' . $extension;
+ try {
+ $image = $imageRepo->saveNewFromData($imageName, base64_decode($base64ImageData), 'gallery', $page->id);
+ $imageNode->setAttribute('src', $image->url);
+ } catch (ImageUploadException $exception) {
+ $imageNode->setAttribute('src', '');
+ }
+ }
+
+ // Generate inner html as a string
+ $html = '';
+ foreach ($childNodes as $childNode) {
+ $html .= $doc->saveHTML($childNode);
+ }
+
+ return $html;
+ }
+
/**
* Formats a page's html to be tagged correctly within the system.
*/
protected function formatHtml(string $htmlText): string
{
- if ($htmlText == '') {
+ if (empty($htmlText)) {
return $htmlText;
}
- libxml_use_internal_errors(true);
- $doc = new DOMDocument();
- $doc->loadHTML(mb_convert_encoding($htmlText, 'HTML-ENTITIES', 'UTF-8'));
-
+ $doc = $this->loadDocumentFromHtml($htmlText);
$container = $doc->documentElement;
$body = $container->childNodes->item(0);
$childNodes = $body->childNodes;
protected function updateLinks(DOMXPath $xpath, string $old, string $new)
{
$old = str_replace('"', '', $old);
- $matchingLinks = $xpath->query('//body//*//*[@href="'.$old.'"]');
+ $matchingLinks = $xpath->query('//body//*//*[@href="' . $old . '"]');
foreach ($matchingLinks as $domElem) {
$domElem->setAttribute('href', $new);
}
/**
* Render the page for viewing
*/
- public function render(bool $blankIncludes = false) : string
+ public function render(bool $blankIncludes = false): string
{
$content = $this->page->html;
if (!config('app.allow_content_scripts')) {
- $content = $this->escapeScripts($content);
+ $content = HtmlContentFilter::removeScripts($content);
}
if ($blankIncludes) {
return [];
}
- libxml_use_internal_errors(true);
- $doc = new DOMDocument();
- $doc->loadHTML(mb_convert_encoding($htmlContent, 'HTML-ENTITIES', 'UTF-8'));
+ $doc = $this->loadDocumentFromHtml($htmlContent);
$xPath = new DOMXPath($doc);
$headers = $xPath->query("//h1|//h2|//h3|//h4|//h5|//h6");
/**
* Remove any page include tags within the given HTML.
*/
- protected function blankPageIncludes(string $html) : string
+ protected function blankPageIncludes(string $html): string
{
return preg_replace("/{{@\s?([0-9].*?)}}/", '', $html);
}
/**
* Parse any include tags "{{@<page_id>#section}}" to be part of the page.
*/
- protected function parsePageIncludes(string $html) : string
+ protected function parsePageIncludes(string $html): string
{
$matches = [];
preg_match_all("/{{@\s?([0-9].*?)}}/", $html, $matches);
protected function fetchSectionOfPage(Page $page, string $sectionId): string
{
$topLevelTags = ['table', 'ul', 'ol'];
- $doc = new DOMDocument();
- libxml_use_internal_errors(true);
- $doc->loadHTML(mb_convert_encoding('<body>'.$page->html.'</body>', 'HTML-ENTITIES', 'UTF-8'));
+ $doc = $this->loadDocumentFromHtml($page->html);
// Search included content for the id given and blank out if not exists.
$matchingElem = $doc->getElementById($sectionId);
}
/**
- * Escape script tags within HTML content.
+ * Create and load a DOMDocument from the given html content.
*/
- protected function escapeScripts(string $html) : string
+ protected function loadDocumentFromHtml(string $html): DOMDocument
{
- if (empty($html)) {
- return $html;
- }
-
libxml_use_internal_errors(true);
$doc = new DOMDocument();
+ $html = '<body>' . $html . '</body>';
$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
- $xPath = new DOMXPath($doc);
-
- // Remove standard script tags
- $scriptElems = $xPath->query('//script');
- foreach ($scriptElems as $scriptElem) {
- $scriptElem->parentNode->removeChild($scriptElem);
- }
-
- // Remove clickable links to JavaScript URI
- $badLinks = $xPath->query('//*[contains(@href, \'javascript:\')]');
- foreach ($badLinks as $badLink) {
- $badLink->parentNode->removeChild($badLink);
- }
-
- // Remove forms with calls to JavaScript URI
- $badForms = $xPath->query('//*[contains(@action, \'javascript:\')] | //*[contains(@formaction, \'javascript:\')]');
- foreach ($badForms as $badForm) {
- $badForm->parentNode->removeChild($badForm);
- }
-
- // Remove meta tag to prevent external redirects
- $metaTags = $xPath->query('//meta[contains(@content, \'url\')]');
- foreach ($metaTags as $metaTag) {
- $metaTag->parentNode->removeChild($metaTag);
- }
-
- // Remove data or JavaScript iFrames
- $badIframes = $xPath->query('//*[contains(@src, \'data:\')] | //*[contains(@src, \'javascript:\')] | //*[@srcdoc]');
- foreach ($badIframes as $badIframe) {
- $badIframe->parentNode->removeChild($badIframe);
- }
-
- // Remove 'on*' attributes
- $onAttributes = $xPath->query('//@*[starts-with(name(), \'on\')]');
- foreach ($onAttributes as $attr) {
- /** @var \DOMAttr $attr*/
- $attrName = $attr->nodeName;
- $attr->parentNode->removeAttribute($attrName);
- }
-
- $html = '';
- $topElems = $doc->documentElement->childNodes->item(0)->childNodes;
- foreach ($topElems as $child) {
- $html .= $doc->saveHTML($child);
- }
-
- return $html;
+ return $doc;
}
}
protected function destroyPage(Page $page): int
{
$this->destroyCommonRelations($page);
+ $page->allRevisions()->delete();
// Delete Attached Files
$attachmentService = app(AttachmentService::class);
$entity->jointPermissions()->delete();
$entity->searchTerms()->delete();
$entity->deletions()->delete();
+ $entity->favourites()->delete();
if ($entity instanceof HasCoverImage && $entity->cover) {
$imageService = app()->make(ImageService::class);
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\HttpException;
-use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class Handler extends ExceptionHandler
{
return $this->renderApiException($e);
}
- // Handle notify exceptions which will redirect to the
- // specified location then show a notification message.
- if ($this->isExceptionType($e, NotifyException::class)) {
- $message = $this->getOriginalMessage($e);
- if (!empty($message)) {
- session()->flash('error', $message);
- }
- return redirect($e->redirectLocation);
- }
-
- // Handle pretty exceptions which will show a friendly application-fitting page
- // Which will include the basic message to point the user roughly to the cause.
- if ($this->isExceptionType($e, PrettyException::class) && !config('app.debug')) {
- $message = $this->getOriginalMessage($e);
- $code = ($e->getCode() === 0) ? 500 : $e->getCode();
- return response()->view('errors/' . $code, ['message' => $message], $code);
- }
-
- // Handle 404 errors with a loaded session to enable showing user-specific information
- if ($this->isExceptionType($e, NotFoundHttpException::class)) {
- return \Route::respondWithRoute('fallback');
- }
-
return parent::render($request, $e);
}
return new JsonResponse($responseData, $code, $headers);
}
- /**
- * Check the exception chain to compare against the original exception type.
- */
- protected function isExceptionType(Exception $e, string $type): bool
- {
- do {
- if (is_a($e, $type)) {
- return true;
- }
- } while ($e = $e->getPrevious());
- return false;
- }
-
- /**
- * Get original exception message.
- */
- protected function getOriginalMessage(Exception $e): string
- {
- do {
- $message = $e->getMessage();
- } while ($e = $e->getPrevious());
- return $message;
- }
-
/**
* Convert an authentication exception into an unauthenticated response.
*
<?php namespace BookStack\Exceptions;
-class NotifyException extends \Exception
-{
+use Exception;
+use Illuminate\Contracts\Support\Responsable;
+class NotifyException extends Exception implements Responsable
+{
public $message;
public $redirectLocation;
$this->redirectLocation = $redirectLocation;
parent::__construct();
}
+
+ /**
+ * Send the response for this type of exception.
+ * @inheritdoc
+ */
+ public function toResponse($request)
+ {
+ $message = $this->getMessage();
+
+ if (!empty($message)) {
+ session()->flash('error', $message);
+ }
+
+ return redirect($this->redirectLocation);
+ }
}
<?php namespace BookStack\Exceptions;
-class PrettyException extends \Exception
+use Exception;
+use Illuminate\Contracts\Support\Responsable;
+
+class PrettyException extends Exception implements Responsable
{
+ /**
+ * @var ?string
+ */
+ protected $subtitle = null;
+
+ /**
+ * @var ?string
+ */
+ protected $details = null;
+
+ /**
+ * Render a response for when this exception occurs.
+ * @inheritdoc
+ */
+ public function toResponse($request)
+ {
+ $code = ($this->getCode() === 0) ? 500 : $this->getCode();
+ return response()->view('errors.' . $code, [
+ 'message' => $this->getMessage(),
+ 'subtitle' => $this->subtitle,
+ 'details' => $this->details,
+ ], $code);
+ }
+
+ public function setSubtitle(string $subtitle): self
+ {
+ $this->subtitle = $subtitle;
+ return $this;
+ }
+ public function setDetails(string $details): self
+ {
+ $this->details = $details;
+ return $this;
+ }
}
+++ /dev/null
-<?php namespace BookStack\Facades;
-
-use Illuminate\Support\Facades\Facade;
-
-class Images extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'images';
- }
-}
+++ /dev/null
-<?php namespace BookStack\Facades;
-
-use Illuminate\Support\Facades\Facade;
-
-class Views extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'views';
- }
-}
$textContent = $this->exportFormatter->bookToPlainText($book);
return $this->downloadResponse($textContent, $book->slug . '.txt');
}
+
+ /**
+ * Export a book as a markdown file.
+ */
+ public function exportMarkdown(int $id)
+ {
+ $book = Book::visible()->findOrFail($id);
+ $markdown = $this->exportFormatter->bookToMarkdown($book);
+ return $this->downloadResponse($markdown, $book->slug . '.md');
+ }
}
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Tools\ExportFormatter;
-use BookStack\Entities\Repos\BookRepo;
use Throwable;
class ChapterExportApiController extends ApiController
$textContent = $this->exportFormatter->chapterToPlainText($chapter);
return $this->downloadResponse($textContent, $chapter->slug . '.txt');
}
+
+ /**
+ * Export a chapter as a markdown file.
+ */
+ public function exportMarkdown(int $id)
+ {
+ $chapter = Chapter::visible()->findOrFail($id);
+ $markdown = $this->exportFormatter->chapterToMarkdown($chapter);
+ return $this->downloadResponse($markdown, $chapter->slug . '.md');
+ }
}
*
* Any HTML content provided should be kept to a single-block depth of plain HTML
* elements to remain compatible with the BookStack front-end and editors.
+ * Any images included via base64 data URIs will be extracted and saved as gallery
+ * images against the page during upload.
*/
public function create(Request $request)
{
$textContent = $this->exportFormatter->pageToPlainText($page);
return $this->downloadResponse($textContent, $page->slug . '.txt');
}
+
+ /**
+ * Export a page as a markdown file.
+ */
+ public function exportMarkdown(int $id)
+ {
+ $page = Page::visible()->findOrFail($id);
+ $markdown = $this->exportFormatter->pageToMarkdown($page);
+ return $this->downloadResponse($markdown, $page->slug . '.md');
+ }
}
class AttachmentController extends Controller
{
protected $attachmentService;
- protected $attachment;
protected $pageRepo;
/**
* AttachmentController constructor.
*/
- public function __construct(AttachmentService $attachmentService, Attachment $attachment, PageRepo $pageRepo)
+ public function __construct(AttachmentService $attachmentService, PageRepo $pageRepo)
{
$this->attachmentService = $attachmentService;
- $this->attachment = $attachment;
$this->pageRepo = $pageRepo;
}
'file' => 'required|file'
]);
- $attachment = $this->attachment->newQuery()->findOrFail($attachmentId);
+ $attachment = Attachment::query()->findOrFail($attachmentId);
$this->checkOwnablePermission('view', $attachment->page);
$this->checkOwnablePermission('page-update', $attachment->page);
$this->checkOwnablePermission('attachment-create', $attachment);
*/
public function getUpdateForm(string $attachmentId)
{
- $attachment = $this->attachment->findOrFail($attachmentId);
+ $attachment = Attachment::query()->findOrFail($attachmentId);
$this->checkOwnablePermission('page-update', $attachment->page);
$this->checkOwnablePermission('attachment-create', $attachment);
*/
public function update(Request $request, string $attachmentId)
{
- $attachment = $this->attachment->newQuery()->findOrFail($attachmentId);
-
+ /** @var Attachment $attachment */
+ $attachment = Attachment::query()->findOrFail($attachmentId);
try {
$this->validate($request, [
'attachment_edit_name' => 'required|string|min:1|max:255',
$attachmentName = $request->get('attachment_link_name');
$link = $request->get('attachment_link_url');
- $attachment = $this->attachmentService->saveNewFromLink($attachmentName, $link, intval($pageId));
+ $this->attachmentService->saveNewFromLink($attachmentName, $link, intval($pageId));
return view('attachments.manager-link-form', [
'pageId' => $pageId,
* @throws FileNotFoundException
* @throws NotFoundException
*/
- public function get(string $attachmentId)
+ public function get(Request $request, string $attachmentId)
{
- $attachment = $this->attachment->findOrFail($attachmentId);
+ /** @var Attachment $attachment */
+ $attachment = Attachment::query()->findOrFail($attachmentId);
try {
$page = $this->pageRepo->getById($attachment->uploaded_to);
} catch (NotFoundException $exception) {
return redirect($attachment->path);
}
+ $fileName = $attachment->getFileName();
$attachmentContents = $this->attachmentService->getAttachmentFromStorage($attachment);
- return $this->downloadResponse($attachmentContents, $attachment->getFileName());
+
+ if ($request->get('open') === 'true') {
+ return $this->inlineDownloadResponse($attachmentContents, $fileName);
+ }
+ return $this->downloadResponse($attachmentContents, $fileName);
}
/**
*/
public function delete(string $attachmentId)
{
- $attachment = $this->attachment->findOrFail($attachmentId);
+ /** @var Attachment $attachment */
+ $attachment = Attachment::query()->findOrFail($attachmentId);
$this->checkOwnablePermission('attachment-delete', $attachment);
$this->attachmentService->deleteFile($attachment);
return response()->json(['message' => trans('entities.attachments_deleted')]);
use BookStack\Theming\ThemeEvents;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
+use Illuminate\Validation\ValidationException;
class LoginController extends Controller
{
return redirect('/login');
}
+
+ /**
+ * Get the failed login response instance.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @return \Symfony\Component\HttpFoundation\Response
+ *
+ * @throws \Illuminate\Validation\ValidationException
+ */
+ protected function sendFailedLoginResponse(Request $request)
+ {
+ throw ValidationException::withMessages([
+ $this->username() => [trans('auth.failed')],
+ ])->redirectTo('/login');
+ }
}
use Activity;
use BookStack\Actions\ActivityType;
+use BookStack\Actions\View;
use BookStack\Entities\Tools\BookContents;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Tools\PermissionsUpdater;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Throwable;
-use Views;
class BookController extends Controller
{
$bookChildren = (new BookContents($book))->getTree(true);
$bookParentShelves = $book->shelves()->visible()->get();
- Views::add($book);
+ View::incrementFor($book);
if ($request->has('shelf')) {
$this->entityContextManager->setShelfContext(intval($request->get('shelf')));
}
$textContent = $this->exportFormatter->bookToPlainText($book);
return $this->downloadResponse($textContent, $bookSlug . '.txt');
}
+
+ /**
+ * Export a book as a markdown file.
+ */
+ public function markdown(string $bookSlug)
+ {
+ $book = $this->bookRepo->getBySlug($bookSlug);
+ $textContent = $this->exportFormatter->bookToMarkdown($book);
+ return $this->downloadResponse($textContent, $bookSlug . '.md');
+ }
}
<?php namespace BookStack\Http\Controllers;
use Activity;
+use BookStack\Actions\View;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Tools\PermissionsUpdater;
use BookStack\Entities\Tools\ShelfContext;
->values()
->all();
- Views::add($shelf);
+ View::incrementFor($shelf);
$this->entityContextManager->setShelfContext($shelf->id);
$view = setting()->getForCurrentUser('bookshelf_view_type');
<?php namespace BookStack\Http\Controllers;
+use BookStack\Actions\View;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Tools\BookContents;
use BookStack\Entities\Repos\ChapterRepo;
+use BookStack\Entities\Tools\NextPreviousContentLocator;
use BookStack\Entities\Tools\PermissionsUpdater;
use BookStack\Exceptions\MoveOperationException;
use BookStack\Exceptions\NotFoundException;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Throwable;
-use Views;
class ChapterController extends Controller
{
$sidebarTree = (new BookContents($chapter->book))->getTree();
$pages = $chapter->getVisiblePages();
- Views::add($chapter);
+ $nextPreviousLocator = new NextPreviousContentLocator($chapter, $sidebarTree);
+ View::incrementFor($chapter);
$this->setPageTitle($chapter->getShortName());
return view('chapters.show', [
'chapter' => $chapter,
'current' => $chapter,
'sidebarTree' => $sidebarTree,
- 'pages' => $pages
+ 'pages' => $pages,
+ 'next' => $nextPreviousLocator->getNext(),
+ 'previous' => $nextPreviousLocator->getPrevious(),
]);
}
$chapterText = $this->exportFormatter->chapterToPlainText($chapter);
return $this->downloadResponse($chapterText, $chapterSlug . '.txt');
}
+
+ /**
+ * Export a chapter to a simple markdown file.
+ * @throws NotFoundException
+ */
+ public function markdown(string $bookSlug, string $chapterSlug)
+ {
+ // TODO: This should probably export to a zip file.
+ $chapter = $this->chapterRepo->getBySlug($bookSlug, $chapterSlug);
+ $chapterText = $this->exportFormatter->chapterToMarkdown($chapter);
+ return $this->downloadResponse($chapterText, $chapterSlug . '.md');
+ }
}
use BookStack\Interfaces\Loggable;
use BookStack\HasCreatorAndUpdater;
use BookStack\Model;
+use finfo;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Exceptions\HttpResponseException;
]);
}
+ /**
+ * Create a file download response that provides the file with a content-type
+ * correct for the file, in a way so the browser can show the content in browser.
+ */
+ protected function inlineDownloadResponse(string $content, string $fileName): Response
+ {
+ $finfo = new finfo(FILEINFO_MIME_TYPE);
+ $mime = $finfo->buffer($content) ?: 'application/octet-stream';
+ return response()->make($content, 200, [
+ 'Content-Type' => $mime,
+ 'Content-Disposition' => 'inline; filename="' . $fileName . '"'
+ ]);
+ }
+
/**
* Show a positive, successful notification to the user on next view load.
*/
--- /dev/null
+<?php
+
+namespace BookStack\Http\Controllers;
+
+use BookStack\Entities\Models\Entity;
+use BookStack\Entities\Queries\TopFavourites;
+use BookStack\Interfaces\Favouritable;
+use BookStack\Model;
+use Illuminate\Http\Request;
+
+class FavouriteController extends Controller
+{
+ /**
+ * Show a listing of all favourite items for the current user.
+ */
+ public function index(Request $request)
+ {
+ $viewCount = 20;
+ $page = intval($request->get('page', 1));
+ $favourites = (new TopFavourites)->run($viewCount + 1, (($page - 1) * $viewCount));
+
+ $hasMoreLink = ($favourites->count() > $viewCount) ? url("/favourites?page=" . ($page+1)) : null;
+
+ return view('common.detailed-listing-with-more', [
+ 'title' => trans('entities.my_favourites'),
+ 'entities' => $favourites->slice(0, $viewCount),
+ 'hasMoreLink' => $hasMoreLink,
+ ]);
+ }
+
+ /**
+ * Add a new item as a favourite.
+ */
+ public function add(Request $request)
+ {
+ $favouritable = $this->getValidatedModelFromRequest($request);
+ $favouritable->favourites()->firstOrCreate([
+ 'user_id' => user()->id,
+ ]);
+
+ $this->showSuccessNotification(trans('activities.favourite_add_notification', [
+ 'name' => $favouritable->name,
+ ]));
+ return redirect()->back();
+ }
+
+ /**
+ * Remove an item as a favourite.
+ */
+ public function remove(Request $request)
+ {
+ $favouritable = $this->getValidatedModelFromRequest($request);
+ $favouritable->favourites()->where([
+ 'user_id' => user()->id,
+ ])->delete();
+
+ $this->showSuccessNotification(trans('activities.favourite_remove_notification', [
+ 'name' => $favouritable->name,
+ ]));
+ return redirect()->back();
+ }
+
+ /**
+ * @throws \Illuminate\Validation\ValidationException
+ * @throws \Exception
+ */
+ protected function getValidatedModelFromRequest(Request $request): Favouritable
+ {
+ $modelInfo = $this->validate($request, [
+ 'type' => 'required|string',
+ 'id' => 'required|integer',
+ ]);
+
+ if (!class_exists($modelInfo['type'])) {
+ throw new \Exception('Model not found');
+ }
+
+ /** @var Model $model */
+ $model = new $modelInfo['type'];
+ if (! $model instanceof Favouritable) {
+ throw new \Exception('Model not favouritable');
+ }
+
+ $modelInstance = $model->newQuery()
+ ->where('id', '=', $modelInfo['id'])
+ ->first(['id', 'name']);
+
+ $inaccessibleEntity = ($modelInstance instanceof Entity && !userCan('view', $modelInstance));
+ if (is_null($modelInstance) || $inaccessibleEntity) {
+ throw new \Exception('Model instance not found');
+ }
+
+ return $modelInstance;
+ }
+}
use Activity;
use BookStack\Entities\Models\Book;
+use BookStack\Entities\Queries\RecentlyViewed;
+use BookStack\Entities\Queries\TopFavourites;
use BookStack\Entities\Tools\PageContent;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Repos\BookRepo;
use BookStack\Entities\Repos\BookshelfRepo;
-use Illuminate\Http\Response;
use Views;
class HomeController extends Controller
$recentFactor = count($draftPages) > 0 ? 0.5 : 1;
$recents = $this->isSignedIn() ?
- Views::getUserRecentlyViewed(12*$recentFactor, 1)
+ (new RecentlyViewed)->run(12*$recentFactor, 1)
: Book::visible()->orderBy('created_at', 'desc')->take(12 * $recentFactor)->get();
+ $favourites = (new TopFavourites)->run(6);
$recentlyUpdatedPages = Page::visible()->with('book')
->where('draft', false)
->orderBy('updated_at', 'desc')
- ->take(12)
+ ->take($favourites->count() > 0 ? 6 : 12)
->get();
$homepageOptions = ['default', 'books', 'bookshelves', 'page'];
'recents' => $recents,
'recentlyUpdatedPages' => $recentlyUpdatedPages,
'draftPages' => $draftPages,
+ 'favourites' => $favourites,
];
// Add required list ordering & sorting for books & shelves views.
*/
public function customHeadContent()
{
- return view('partials.custom-head-content');
+ return view('partials.custom-head');
}
/**
<?php namespace BookStack\Http\Controllers\Images;
use BookStack\Exceptions\ImageUploadException;
+use BookStack\Exceptions\NotFoundException;
use BookStack\Http\Controllers\Controller;
use BookStack\Uploads\Image;
use BookStack\Uploads\ImageRepo;
/**
* Provide an image file from storage.
+ * @throws NotFoundException
*/
public function showImage(string $path)
{
$path = storage_path('uploads/images/' . $path);
if (!file_exists($path)) {
- abort(404);
+ throw (new NotFoundException(trans('errors.image_not_found')))
+ ->setSubtitle(trans('errors.image_not_found_subtitle'))
+ ->setDetails(trans('errors.image_not_found_details'));
}
return response()->file($path);
<?php namespace BookStack\Http\Controllers;
+use BookStack\Actions\View;
use BookStack\Entities\Tools\BookContents;
+use BookStack\Entities\Tools\NextPreviousContentLocator;
use BookStack\Entities\Tools\PageContent;
use BookStack\Entities\Tools\PageEditActivity;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Repos\PageRepo;
use BookStack\Entities\Tools\PermissionsUpdater;
use BookStack\Exceptions\NotFoundException;
-use BookStack\Exceptions\NotifyException;
use BookStack\Exceptions\PermissionsException;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Throwable;
-use Views;
class PageController extends Controller
{
$page->load(['comments.createdBy']);
}
- Views::add($page);
+ $nextPreviousLocator = new NextPreviousContentLocator($page, $sidebarTree);
+
+ View::incrementFor($page);
$this->setPageTitle($page->getShortName());
return view('pages.show', [
'page' => $page,
'current' => $page,
'sidebarTree' => $sidebarTree,
'commentsEnabled' => $commentsEnabled,
- 'pageNav' => $pageNav
+ 'pageNav' => $pageNav,
+ 'next' => $nextPreviousLocator->getNext(),
+ 'previous' => $nextPreviousLocator->getPrevious(),
]);
}
$updateTime = $draft->updated_at->timestamp;
return response()->json([
- 'status' => 'success',
- 'message' => trans('entities.pages_edit_draft_save_at'),
+ 'status' => 'success',
+ 'message' => trans('entities.pages_edit_draft_save_at'),
'timestamp' => $updateTime
]);
}
{
$page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-delete', $page);
- $this->setPageTitle(trans('entities.pages_delete_named', ['pageName'=>$page->getShortName()]));
+ $this->setPageTitle(trans('entities.pages_delete_named', ['pageName' => $page->getShortName()]));
return view('pages.delete', [
'book' => $page->book,
'page' => $page,
{
$page = $this->pageRepo->getById($pageId);
$this->checkOwnablePermission('page-update', $page);
- $this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName'=>$page->getShortName()]));
+ $this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName' => $page->getShortName()]));
return view('pages.delete', [
'book' => $page->book,
'page' => $page,
* Remove the specified page from storage.
* @throws NotFoundException
* @throws Throwable
- * @throws NotifyException
*/
public function destroy(string $bookSlug, string $pageSlug)
{
/**
* Remove the specified draft page from storage.
* @throws NotFoundException
- * @throws NotifyException
* @throws Throwable
*/
public function destroyDraft(string $bookSlug, int $pageId)
->paginate(20)
->setPath(url('/pages/recently-updated'));
- return view('pages.detailed-listing', [
+ return view('common.detailed-listing-paginated', [
'title' => trans('entities.recently_updated_pages'),
- 'pages' => $pages
+ 'entities' => $pages
]);
}
try {
$parent = $this->pageRepo->move($page, $entitySelection);
} catch (Exception $exception) {
- if ($exception instanceof PermissionsException) {
+ if ($exception instanceof PermissionsException) {
$this->showPermissionError();
}
try {
$pageCopy = $this->pageRepo->copy($page, $entitySelection, $newName);
} catch (Exception $exception) {
- if ($exception instanceof PermissionsException) {
+ if ($exception instanceof PermissionsException) {
$this->showPermissionError();
}
$page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
$this->checkOwnablePermission('restrictions-manage', $page);
return view('pages.permissions', [
- 'page' => $page,
+ 'page' => $page,
]);
}
$pageText = $this->exportFormatter->pageToPlainText($page);
return $this->downloadResponse($pageText, $pageSlug . '.txt');
}
+
+ /**
+ * Export a page to a simple markdown .md file.
+ * @throws NotFoundException
+ */
+ public function markdown(string $bookSlug, string $pageSlug)
+ {
+ $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $pageText = $this->exportFormatter->pageToMarkdown($page);
+ return $this->downloadResponse($pageText, $pageSlug . '.md');
+ }
}
<?php namespace BookStack\Http\Controllers;
-use BookStack\Actions\ViewService;
+use BookStack\Entities\Queries\Popular;
use BookStack\Entities\Tools\SearchRunner;
use BookStack\Entities\Tools\ShelfContext;
use BookStack\Entities\Tools\SearchOptions;
class SearchController extends Controller
{
- protected $viewService;
protected $searchRunner;
protected $entityContextManager;
public function __construct(
- ViewService $viewService,
SearchRunner $searchRunner,
ShelfContext $entityContextManager
) {
- $this->viewService = $viewService;
$this->searchRunner = $searchRunner;
$this->entityContextManager = $entityContextManager;
}
$searchTerm .= ' {type:'. implode('|', $entityTypes) .'}';
$entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 20, $permission)['results'];
} else {
- $entities = $this->viewService->getPopular(20, 0, $entityTypes, $permission);
+ $entities = (new Popular)->run(20, 0, $entityTypes, $permission);
}
return view('search.entity-ajax-list', ['entities' => $entities]);
'es_AR' => 'es_AR',
'fr' => 'fr_FR',
'he' => 'he_IL',
+ 'hr' => 'hr_HR',
'id' => 'id_ID',
'it' => 'it_IT',
'ja' => 'ja',
--- /dev/null
+<?php namespace BookStack\Interfaces;
+
+use Illuminate\Database\Eloquent\Relations\MorphMany;
+
+interface Favouritable
+{
+ /**
+ * Get the related favourite instances.
+ */
+ public function favourites(): MorphMany;
+}
\ No newline at end of file
--- /dev/null
+<?php namespace BookStack\Interfaces;
+
+use Illuminate\Database\Eloquent\Relations\MorphMany;
+
+interface Viewable
+{
+ /**
+ * Get all view instances for this viewable model.
+ */
+ public function views(): MorphMany;
+}
\ No newline at end of file
namespace BookStack\Providers;
use BookStack\Actions\ActivityService;
-use BookStack\Actions\ViewService;
use BookStack\Auth\Permissions\PermissionService;
use BookStack\Theming\ThemeService;
use BookStack\Uploads\ImageService;
return $this->app->make(ActivityService::class);
});
- $this->app->singleton('views', function () {
- return $this->app->make(ViewService::class);
- });
-
$this->app->singleton('images', function () {
return $this->app->make(ImageService::class);
});
/**
* @see SocialAuthService::addSocialDriver
*/
- public function addSocialDriver(string $driverName, array $config, string $socialiteHandler)
+ public function addSocialDriver(string $driverName, array $config, string $socialiteHandler, callable $configureForRedirect = null)
{
$socialAuthService = app()->make(SocialAuthService::class);
- $socialAuthService->addSocialDriver($driverName, $config, $socialiteHandler);
+ $socialAuthService->addSocialDriver($driverName, $config, $socialiteHandler, $configureForRedirect);
}
}
\ No newline at end of file
use BookStack\Entities\Models\Page;
use BookStack\Model;
use BookStack\Traits\HasCreatorAndUpdater;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property int id
* @property string name
* @property string path
* @property string extension
+ * @property ?Page page
* @property bool external
*/
class Attachment extends Model
/**
* Get the page this file was uploaded to.
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
- public function page()
+ public function page(): BelongsTo
{
return $this->belongsTo(Page::class, 'uploaded_to');
}
/**
* Get the url of this file.
*/
- public function getUrl(): string
+ public function getUrl($openInline = false): string
{
if ($this->external && strpos($this->path, 'http') !== 0) {
return $this->path;
}
- return url('/attachments/' . $this->id);
+ return url('/attachments/' . $this->id . ($openInline ? '?open=true' : ''));
}
/**
use BookStack\Exceptions\FileUploadException;
use Exception;
use Illuminate\Contracts\Filesystem\Factory as FileSystem;
+use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Contracts\Filesystem\Filesystem as FileSystemInstance;
use Illuminate\Support\Str;
+use Log;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class AttachmentService
/**
* Get an attachment from storage.
- * @param Attachment $attachment
- * @return string
- * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
+ * @throws FileNotFoundException
*/
- public function getAttachmentFromStorage(Attachment $attachment)
+ public function getAttachmentFromStorage(Attachment $attachment): string
{
return $this->getStorage()->get($attachment->path);
}
try {
$storage->put($attachmentPath, $attachmentData);
} catch (Exception $e) {
+ Log::error('Error when attempting file upload:' . $e->getMessage());
throw new FileUploadException(trans('errors.path_not_writable', ['filePath' => $attachmentPath]));
}
use BookStack\Entities\Models\Page;
use BookStack\Model;
use BookStack\Traits\HasCreatorAndUpdater;
-use Images;
+/**
+ * @property int $id
+ * @property string $name
+ * @property string $url
+ * @property string $path
+ * @property string $type
+ * @property int $uploaded_to
+ * @property int $created_by
+ * @property int $updated_by
+ */
class Image extends Model
{
use HasCreatorAndUpdater;
/**
* Get a thumbnail for this image.
- * @param int $width
- * @param int $height
- * @param bool|false $keepRatio
- * @return string
* @throws \Exception
*/
- public function getThumb($width, $height, $keepRatio = false)
+ public function getThumb(int $width, int $height, bool $keepRatio = false): string
{
- return Images::getThumbnail($this, $width, $height, $keepRatio);
+ return app()->make(ImageService::class)->getThumbnail($this, $width, $height, $keepRatio);
}
/**
* Get the page this image has been uploaded to.
* Only applicable to gallery or drawio image types.
- * @return Page|null
*/
- public function getPage()
+ public function getPage(): ?Page
{
return $this->belongsTo(Page::class, 'uploaded_to')->first();
}
return $image;
}
+ /**
+ * Save a new image from an existing image data string.
+ * @throws ImageUploadException
+ */
+ public function saveNewFromData(string $imageName, string $imageData, string $type, int $uploadedTo = 0)
+ {
+ $image = $this->imageService->saveNew($imageName, $imageData, $type, $uploadedTo);
+ $this->loadThumbs($image);
+ return $image;
+ }
+
/**
* Save a drawing the the database.
* @throws ImageUploadException
use Illuminate\Contracts\Filesystem\Factory as FileSystem;
use Illuminate\Contracts\Filesystem\Filesystem as FileSystemInstance;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
+use Illuminate\Contracts\Filesystem\Filesystem as Storage;
use Illuminate\Support\Str;
use Intervention\Image\Exception\NotSupportedException;
use Intervention\Image\ImageManager;
}
try {
- $storage->put($fullPath, $imageData);
- $storage->setVisibility($fullPath, 'public');
+ $this->saveImageDataInPublicSpace($storage, $fullPath, $imageData);
} catch (Exception $e) {
+ \Log::error('Error when attempting image upload:' . $e->getMessage());
throw new ImageUploadException(trans('errors.path_not_writable', ['filePath' => $fullPath]));
}
return $image;
}
+ /**
+ * Save image data for the given path in the public space, if possible,
+ * for the provided storage mechanism.
+ */
+ protected function saveImageDataInPublicSpace(Storage $storage, string $path, string $data)
+ {
+ $storage->put($path, $data);
+
+ // Set visibility when a non-AWS-s3, s3-like storage option is in use.
+ // Done since this call can break s3-like services but desired for other image stores.
+ // Attempting to set ACL during above put request requires different permissions
+ // hence would technically be a breaking change for actual s3 usage.
+ $usingS3 = strtolower(config('filesystems.images')) === 's3';
+ $usingS3Like = $usingS3 && !is_null(config('filesystems.disks.s3.endpoint'));
+ if (!$usingS3Like) {
+ $storage->setVisibility($path, 'public');
+ }
+ }
+
/**
* Clean up an image file name to be both URL and storage safe.
*/
$thumbData = $this->resizeImage($storage->get($imagePath), $width, $height, $keepRatio);
- $storage->put($thumbFilePath, $thumbData);
- $storage->setVisibility($thumbFilePath, 'public');
+ $this->saveImageDataInPublicSpace($storage, $thumbFilePath, $thumbData);
$this->cache->put('images-' . $image->id . '-' . $thumbFilePath, $thumbFilePath, 60 * 60 * 72);
}
try {
+ $this->destroyAllForUser($user);
$avatar = $this->saveAvatarImage($user);
$user->avatar()->associate($avatar);
$user->save();
}
}
+ /**
+ * Assign a new avatar image to the given user using the given image data.
+ */
+ public function assignToUserFromExistingData(User $user, string $imageData, string $extension): void
+ {
+ try {
+ $this->destroyAllForUser($user);
+ $avatar = $this->createAvatarImageFromData($user, $imageData, $extension);
+ $user->avatar()->associate($avatar);
+ $user->save();
+ } catch (Exception $e) {
+ Log::error('Failed to save user avatar image');
+ }
+ }
+
+ /**
+ * Destroy all user avatars uploaded to the given user.
+ */
+ public function destroyAllForUser(User $user)
+ {
+ $profileImages = Image::query()->where('type', '=', 'user')
+ ->where('uploaded_to', '=', $user->id)
+ ->get();
+
+ foreach ($profileImages as $image) {
+ $this->imageService->destroy($image);
+ }
+ }
+
/**
* Save an avatar image from an external service.
* @throws Exception
];
$userAvatarUrl = strtr($avatarUrl, $replacements);
- $imageName = str_replace(' ', '-', $user->id . '-avatar.png');
$imageData = $this->getAvatarImageData($userAvatarUrl);
+ return $this->createAvatarImageFromData($user, $imageData, 'png');
+ }
+
+ /**
+ * Creates a new image instance and saves it in the system as a new user avatar image.
+ */
+ protected function createAvatarImageFromData(User $user, string $imageData, string $extension): Image
+ {
+ $imageName = str_replace(' ', '-', $user->id . '-avatar.' . $extension);
$image = $this->imageService->saveNew($imageName, $imageData, 'user', $user->id);
$image->created_by = $user->id;
--- /dev/null
+<?php namespace BookStack\Util;
+
+use DOMDocument;
+use DOMNodeList;
+use DOMXPath;
+
+class HtmlContentFilter
+{
+ /**
+ * Remove all of the script elements from the given HTML.
+ */
+ public static function removeScripts(string $html): string
+ {
+ if (empty($html)) {
+ return $html;
+ }
+
+ $html = '<body>' . $html . '</body>';
+ libxml_use_internal_errors(true);
+ $doc = new DOMDocument();
+ $doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
+ $xPath = new DOMXPath($doc);
+
+ // Remove standard script tags
+ $scriptElems = $xPath->query('//script');
+ static::removeNodes($scriptElems);
+
+ // Remove clickable links to JavaScript URI
+ $badLinks = $xPath->query('//*[contains(@href, \'javascript:\')]');
+ static::removeNodes($badLinks);
+
+ // Remove forms with calls to JavaScript URI
+ $badForms = $xPath->query('//*[contains(@action, \'javascript:\')] | //*[contains(@formaction, \'javascript:\')]');
+ static::removeNodes($badForms);
+
+ // Remove meta tag to prevent external redirects
+ $metaTags = $xPath->query('//meta[contains(@content, \'url\')]');
+ static::removeNodes($metaTags);
+
+ // Remove data or JavaScript iFrames
+ $badIframes = $xPath->query('//*[contains(@src, \'data:\')] | //*[contains(@src, \'javascript:\')] | //*[@srcdoc]');
+ static::removeNodes($badIframes);
+
+ // Remove 'on*' attributes
+ $onAttributes = $xPath->query('//@*[starts-with(name(), \'on\')]');
+ foreach ($onAttributes as $attr) {
+ /** @var \DOMAttr $attr*/
+ $attrName = $attr->nodeName;
+ $attr->parentNode->removeAttribute($attrName);
+ }
+
+ $html = '';
+ $topElems = $doc->documentElement->childNodes->item(0)->childNodes;
+ foreach ($topElems as $child) {
+ $html .= $doc->saveHTML($child);
+ }
+
+ return $html;
+ }
+
+ /**
+ * Removed all of the given DOMNodes.
+ */
+ protected static function removeNodes(DOMNodeList $nodes): void
+ {
+ foreach ($nodes as $node) {
+ $node->parentNode->removeChild($node);
+ }
+ }
+}
"php": "^7.3|^8.0",
"ext-curl": "*",
"ext-dom": "*",
+ "ext-fileinfo": "*",
"ext-gd": "*",
"ext-json": "*",
"ext-mbstring": "*",
"laravel/socialite": "^5.1",
"league/commonmark": "^1.5",
"league/flysystem-aws-s3-v3": "^1.0.29",
+ "league/html-to-markdown": "^5.0.0",
"nunomaduro/collision": "^3.1",
"onelogin/php-saml": "^4.0",
"predis/predis": "^1.1.6",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "b26d29958d84c91b164a8234d1a7e9e9",
+ "content-hash": "70a290f0e2112361af4a0abe15148adc",
"packages": [
{
"name": "aws/aws-sdk-php",
- "version": "3.175.0",
+ "version": "3.184.7",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
- "reference": "31baa9e0c4330f01eb74b8a7ef086e9d34f8391e"
+ "reference": "d5d5fe5fdfca6c7a56f2f8364d09c3100d5c2149"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/31baa9e0c4330f01eb74b8a7ef086e9d34f8391e",
- "reference": "31baa9e0c4330f01eb74b8a7ef086e9d34f8391e",
+ "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d5d5fe5fdfca6c7a56f2f8364d09c3100d5c2149",
+ "reference": "d5d5fe5fdfca6c7a56f2f8364d09c3100d5c2149",
"shasum": ""
},
"require": {
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
- "source": "https://github.com/aws/aws-sdk-php/tree/3.175.0"
+ "source": "https://github.com/aws/aws-sdk-php/tree/3.184.7"
},
- "time": "2021-03-19T18:13:22+00:00"
+ "time": "2021-06-21T18:37:16+00:00"
},
{
"name": "barryvdh/laravel-dompdf",
},
{
"name": "doctrine/cache",
- "version": "1.10.2",
+ "version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/cache.git",
- "reference": "13e3381b25847283a91948d04640543941309727"
+ "reference": "c9622c6820d3ede1e2315a6a377ea1076e421d88"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/cache/zipball/13e3381b25847283a91948d04640543941309727",
- "reference": "13e3381b25847283a91948d04640543941309727",
+ "url": "https://api.github.com/repos/doctrine/cache/zipball/c9622c6820d3ede1e2315a6a377ea1076e421d88",
+ "reference": "c9622c6820d3ede1e2315a6a377ea1076e421d88",
"shasum": ""
},
"require": {
"php": "~7.1 || ^8.0"
},
"conflict": {
- "doctrine/common": ">2.2,<2.4"
+ "doctrine/common": ">2.2,<2.4",
+ "psr/cache": ">=3"
},
"require-dev": {
"alcaeus/mongo-php-adapter": "^1.1",
- "doctrine/coding-standard": "^6.0",
+ "cache/integration-tests": "dev-master",
+ "doctrine/coding-standard": "^8.0",
"mongodb/mongodb": "^1.1",
- "phpunit/phpunit": "^7.0",
- "predis/predis": "~1.0"
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+ "predis/predis": "~1.0",
+ "psr/cache": "^1.0 || ^2.0",
+ "symfony/cache": "^4.4 || ^5.2"
},
"suggest": {
"alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.9.x-dev"
- }
- },
"autoload": {
"psr-4": {
"Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
],
"support": {
"issues": "https://github.com/doctrine/cache/issues",
- "source": "https://github.com/doctrine/cache/tree/1.10.x"
+ "source": "https://github.com/doctrine/cache/tree/2.0.3"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2020-07-07T18:54:01+00:00"
+ "time": "2021-05-25T09:43:04+00:00"
},
{
"name": "doctrine/dbal",
- "version": "2.12.1",
+ "version": "2.13.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
- "reference": "adce7a954a1c2f14f85e94aed90c8489af204086"
+ "reference": "8dd39d2ead4409ce652fd4f02621060f009ea5e4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/dbal/zipball/adce7a954a1c2f14f85e94aed90c8489af204086",
- "reference": "adce7a954a1c2f14f85e94aed90c8489af204086",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/8dd39d2ead4409ce652fd4f02621060f009ea5e4",
+ "reference": "8dd39d2ead4409ce652fd4f02621060f009ea5e4",
"shasum": ""
},
"require": {
- "doctrine/cache": "^1.0",
+ "doctrine/cache": "^1.0|^2.0",
+ "doctrine/deprecations": "^0.5.3",
"doctrine/event-manager": "^1.0",
"ext-pdo": "*",
- "php": "^7.3 || ^8"
+ "php": "^7.1 || ^8"
},
"require-dev": {
- "doctrine/coding-standard": "^8.1",
- "jetbrains/phpstorm-stubs": "^2019.1",
- "phpstan/phpstan": "^0.12.40",
- "phpunit/phpunit": "^9.4",
- "psalm/plugin-phpunit": "^0.10.0",
+ "doctrine/coding-standard": "9.0.0",
+ "jetbrains/phpstorm-stubs": "2020.2",
+ "phpstan/phpstan": "0.12.81",
+ "phpunit/phpunit": "^7.5.20|^8.5|9.5.5",
+ "squizlabs/php_codesniffer": "3.6.0",
+ "symfony/cache": "^4.4",
"symfony/console": "^2.0.5|^3.0|^4.0|^5.0",
- "vimeo/psalm": "^3.17.2"
+ "vimeo/psalm": "4.6.4"
},
"suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files."
"bin/doctrine-dbal"
],
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "4.0.x-dev"
- }
- },
"autoload": {
"psr-4": {
"Doctrine\\DBAL\\": "lib/Doctrine/DBAL"
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
- "source": "https://github.com/doctrine/dbal/tree/2.12.1"
+ "source": "https://github.com/doctrine/dbal/tree/2.13.2"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2020-11-14T20:26:58+00:00"
+ "time": "2021-06-18T21:48:39+00:00"
+ },
+ {
+ "name": "doctrine/deprecations",
+ "version": "v0.5.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/deprecations.git",
+ "reference": "9504165960a1f83cc1480e2be1dd0a0478561314"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/9504165960a1f83cc1480e2be1dd0a0478561314",
+ "reference": "9504165960a1f83cc1480e2be1dd0a0478561314",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1|^8.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^6.0|^7.0|^8.0",
+ "phpunit/phpunit": "^7.0|^8.0|^9.0",
+ "psr/log": "^1.0"
+ },
+ "suggest": {
+ "psr/log": "Allows logging deprecations via PSR-3 logger implementation"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
+ "homepage": "https://www.doctrine-project.org/",
+ "support": {
+ "issues": "https://github.com/doctrine/deprecations/issues",
+ "source": "https://github.com/doctrine/deprecations/tree/v0.5.3"
+ },
+ "time": "2021-03-21T12:59:47+00:00"
},
{
"name": "doctrine/event-manager",
},
{
"name": "facade/flare-client-php",
- "version": "1.4.0",
+ "version": "1.8.1",
"source": {
"type": "git",
"url": "https://github.com/facade/flare-client-php.git",
- "reference": "ef0f5bce23b30b32d98fd9bb49c6fa37b40eb546"
+ "reference": "47b639dc02bcfdfc4ebb83de703856fa01e35f5f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/facade/flare-client-php/zipball/ef0f5bce23b30b32d98fd9bb49c6fa37b40eb546",
- "reference": "ef0f5bce23b30b32d98fd9bb49c6fa37b40eb546",
+ "url": "https://api.github.com/repos/facade/flare-client-php/zipball/47b639dc02bcfdfc4ebb83de703856fa01e35f5f",
+ "reference": "47b639dc02bcfdfc4ebb83de703856fa01e35f5f",
"shasum": ""
},
"require": {
],
"support": {
"issues": "https://github.com/facade/flare-client-php/issues",
- "source": "https://github.com/facade/flare-client-php/tree/1.4.0"
+ "source": "https://github.com/facade/flare-client-php/tree/1.8.1"
},
"funding": [
{
"type": "github"
}
],
- "time": "2021-02-16T12:42:06+00:00"
+ "time": "2021-05-31T19:23:29+00:00"
},
{
"name": "facade/ignition",
- "version": "1.16.15",
+ "version": "1.17.0",
"source": {
"type": "git",
"url": "https://github.com/facade/ignition.git",
- "reference": "b6aea4a99303d9d32afd486a285162a89af8a8a3"
+ "reference": "dc49305538aeb77e4c89eba57cee4ceff9e42f33"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/facade/ignition/zipball/b6aea4a99303d9d32afd486a285162a89af8a8a3",
- "reference": "b6aea4a99303d9d32afd486a285162a89af8a8a3",
+ "url": "https://api.github.com/repos/facade/ignition/zipball/dc49305538aeb77e4c89eba57cee4ceff9e42f33",
+ "reference": "dc49305538aeb77e4c89eba57cee4ceff9e42f33",
"shasum": ""
},
"require": {
"issues": "https://github.com/facade/ignition/issues",
"source": "https://github.com/facade/ignition"
},
- "time": "2021-02-15T10:21:49+00:00"
+ "time": "2021-05-25T07:15:52+00:00"
},
{
"name": "facade/ignition-contracts",
},
{
"name": "filp/whoops",
- "version": "2.11.0",
+ "version": "2.13.0",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
- "reference": "f6e14679f948d8a5cfb866fa7065a30c66bd64d3"
+ "reference": "2edbc73a4687d9085c8f20f398eebade844e8424"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/filp/whoops/zipball/f6e14679f948d8a5cfb866fa7065a30c66bd64d3",
- "reference": "f6e14679f948d8a5cfb866fa7065a30c66bd64d3",
+ "url": "https://api.github.com/repos/filp/whoops/zipball/2edbc73a4687d9085c8f20f398eebade844e8424",
+ "reference": "2edbc73a4687d9085c8f20f398eebade844e8424",
"shasum": ""
},
"require": {
],
"support": {
"issues": "https://github.com/filp/whoops/issues",
- "source": "https://github.com/filp/whoops/tree/2.11.0"
+ "source": "https://github.com/filp/whoops/tree/2.13.0"
},
"funding": [
{
"type": "github"
}
],
- "time": "2021-03-19T12:00:00+00:00"
+ "time": "2021-06-04T12:00:00+00:00"
},
{
"name": "guzzlehttp/guzzle",
- "version": "7.2.0",
+ "version": "7.3.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
- "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79"
+ "reference": "7008573787b430c1c1f650e3722d9bba59967628"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle/zipball/0aa74dfb41ae110835923ef10a9d803a22d50e79",
- "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628",
+ "reference": "7008573787b430c1c1f650e3722d9bba59967628",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.4",
- "guzzlehttp/psr7": "^1.7",
+ "guzzlehttp/psr7": "^1.7 || ^2.0",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0"
},
"psr/http-client-implementation": "1.0"
},
"require-dev": {
+ "bamarni/composer-bin-plugin": "^1.4.1",
"ext-curl": "*",
"php-http/client-integration-tests": "^3.0",
"phpunit/phpunit": "^8.5.5 || ^9.3.5",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "7.1-dev"
+ "dev-master": "7.3-dev"
}
},
"autoload": {
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
- "source": "https://github.com/guzzle/guzzle/tree/7.2.0"
+ "source": "https://github.com/guzzle/guzzle/tree/7.3.0"
},
"funding": [
{
"type": "github"
}
],
- "time": "2020-10-10T11:47:56+00:00"
+ "time": "2021-03-23T11:33:13+00:00"
},
{
"name": "guzzlehttp/promises",
},
{
"name": "guzzlehttp/psr7",
- "version": "1.7.0",
+ "version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
- "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3"
+ "reference": "dc960a912984efb74d0a90222870c72c87f10c91"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/psr7/zipball/53330f47520498c0ae1f61f7e2c90f55690c06a3",
- "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91",
+ "reference": "dc960a912984efb74d0a90222870c72c87f10c91",
"shasum": ""
},
"require": {
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
- "source": "https://github.com/guzzle/psr7/tree/1.7.0"
+ "source": "https://github.com/guzzle/psr7/tree/1.8.2"
},
- "time": "2020-09-30T07:37:11+00:00"
+ "time": "2021-04-26T09:17:50+00:00"
},
{
"name": "intervention/image",
},
{
"name": "laravel/framework",
- "version": "v6.20.19",
+ "version": "v6.20.29",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "c25308a00c7bbd38401a6254ab403146da9cfd69"
+ "reference": "00fa9c04aed10d68481f5757b89da0e6798f53b3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/c25308a00c7bbd38401a6254ab403146da9cfd69",
- "reference": "c25308a00c7bbd38401a6254ab403146da9cfd69",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/00fa9c04aed10d68481f5757b89da0e6798f53b3",
+ "reference": "00fa9c04aed10d68481f5757b89da0e6798f53b3",
"shasum": ""
},
"require": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2021-03-16T14:18:55+00:00"
+ "time": "2021-06-22T13:41:06+00:00"
},
{
"name": "laravel/socialite",
- "version": "v5.2.2",
+ "version": "v5.2.3",
"source": {
"type": "git",
"url": "https://github.com/laravel/socialite.git",
- "reference": "8d25d574b4f2005411c0b9cb527ef5e745c1b07d"
+ "reference": "1960802068f81e44b2ae9793932181cf1cb91b5c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/socialite/zipball/8d25d574b4f2005411c0b9cb527ef5e745c1b07d",
- "reference": "8d25d574b4f2005411c0b9cb527ef5e745c1b07d",
+ "url": "https://api.github.com/repos/laravel/socialite/zipball/1960802068f81e44b2ae9793932181cf1cb91b5c",
+ "reference": "1960802068f81e44b2ae9793932181cf1cb91b5c",
"shasum": ""
},
"require": {
"issues": "https://github.com/laravel/socialite/issues",
"source": "https://github.com/laravel/socialite"
},
- "time": "2021-03-02T16:50:47+00:00"
+ "time": "2021-04-06T14:38:16+00:00"
},
{
"name": "league/commonmark",
- "version": "1.5.7",
+ "version": "1.6.4",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
- "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54"
+ "reference": "c3c8b7217c52572fb42aaf84211abccf75a151b2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/11df9b36fd4f1d2b727a73bf14931d81373b9a54",
- "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54",
+ "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/c3c8b7217c52572fb42aaf84211abccf75a151b2",
+ "reference": "c3c8b7217c52572fb42aaf84211abccf75a151b2",
"shasum": ""
},
"require": {
"github/gfm": "0.29.0",
"michelf/php-markdown": "~1.4",
"mikehaertl/php-shellcommand": "^1.4",
- "phpstan/phpstan": "^0.12",
+ "phpstan/phpstan": "^0.12.90",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.2",
"scrutinizer/ocular": "^1.5",
"symfony/finder": "^4.2"
"type": "tidelift"
}
],
- "time": "2020-10-31T13:49:32+00:00"
+ "time": "2021-06-19T20:08:14+00:00"
},
{
"name": "league/flysystem",
},
"time": "2020-10-08T18:58:37+00:00"
},
+ {
+ "name": "league/html-to-markdown",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/html-to-markdown.git",
+ "reference": "c4dbebbebe0fe454b6b38e6c683a977615bd7dc2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/c4dbebbebe0fe454b6b38e6c683a977615bd7dc2",
+ "reference": "c4dbebbebe0fe454b6b38e6c683a977615bd7dc2",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-xml": "*",
+ "php": "^7.2.5 || ^8.0"
+ },
+ "require-dev": {
+ "mikehaertl/php-shellcommand": "^1.1.0",
+ "phpstan/phpstan": "^0.12.82",
+ "phpunit/phpunit": "^8.5 || ^9.2",
+ "scrutinizer/ocular": "^1.6",
+ "unleashedtech/php-coding-standard": "^2.7",
+ "vimeo/psalm": "^4.6"
+ },
+ "bin": [
+ "bin/html-to-markdown"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\HTMLToMarkdown\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Colin O'Dell",
+ "homepage": "https://www.colinodell.com",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Nick Cernis",
+ "homepage": "http://modernnerd.net",
+ "role": "Original Author"
+ }
+ ],
+ "description": "An HTML-to-markdown conversion helper for PHP",
+ "homepage": "https://github.com/thephpleague/html-to-markdown",
+ "keywords": [
+ "html",
+ "markdown"
+ ],
+ "support": {
+ "issues": "https://github.com/thephpleague/html-to-markdown/issues",
+ "source": "https://github.com/thephpleague/html-to-markdown/tree/5.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.colinodell.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.paypal.me/colinpodell/10.00",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/colinodell",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/colinodell",
+ "type": "patreon"
+ }
+ ],
+ "time": "2021-03-29T01:29:08+00:00"
+ },
{
"name": "league/mime-type-detection",
"version": "1.7.0",
},
{
"name": "mtdowling/jmespath.php",
- "version": "2.6.0",
+ "version": "2.6.1",
"source": {
"type": "git",
"url": "https://github.com/jmespath/jmespath.php.git",
- "reference": "42dae2cbd13154083ca6d70099692fef8ca84bfb"
+ "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/42dae2cbd13154083ca6d70099692fef8ca84bfb",
- "reference": "42dae2cbd13154083ca6d70099692fef8ca84bfb",
+ "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/9b87907a81b87bc76d19a7fb2d61e61486ee9edb",
+ "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb",
"shasum": ""
},
"require": {
"symfony/polyfill-mbstring": "^1.17"
},
"require-dev": {
- "composer/xdebug-handler": "^1.4",
+ "composer/xdebug-handler": "^1.4 || ^2.0",
"phpunit/phpunit": "^4.8.36 || ^7.5.15"
},
"bin": [
],
"support": {
"issues": "https://github.com/jmespath/jmespath.php/issues",
- "source": "https://github.com/jmespath/jmespath.php/tree/2.6.0"
+ "source": "https://github.com/jmespath/jmespath.php/tree/2.6.1"
},
- "time": "2020-07-31T21:01:56+00:00"
+ "time": "2021-06-14T00:11:39+00:00"
},
{
"name": "nesbot/carbon",
- "version": "2.46.0",
+ "version": "2.49.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
- "reference": "2fd2c4a77d58a4e95234c8a61c5df1f157a91bf4"
+ "reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/2fd2c4a77d58a4e95234c8a61c5df1f157a91bf4",
- "reference": "2fd2c4a77d58a4e95234c8a61c5df1f157a91bf4",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/93d9db91c0235c486875d22f1e08b50bdf3e6eee",
+ "reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"shasum": ""
},
"require": {
"type": "tidelift"
}
],
- "time": "2021-02-24T17:30:44+00:00"
+ "time": "2021-06-02T07:31:40+00:00"
},
{
"name": "nunomaduro/collision",
},
{
"name": "opis/closure",
- "version": "3.6.1",
+ "version": "3.6.2",
"source": {
"type": "git",
"url": "https://github.com/opis/closure.git",
- "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5"
+ "reference": "06e2ebd25f2869e54a306dda991f7db58066f7f6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/opis/closure/zipball/943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5",
- "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5",
+ "url": "https://api.github.com/repos/opis/closure/zipball/06e2ebd25f2869e54a306dda991f7db58066f7f6",
+ "reference": "06e2ebd25f2869e54a306dda991f7db58066f7f6",
"shasum": ""
},
"require": {
],
"support": {
"issues": "https://github.com/opis/closure/issues",
- "source": "https://github.com/opis/closure/tree/3.6.1"
+ "source": "https://github.com/opis/closure/tree/3.6.2"
},
- "time": "2020-11-07T02:01:34+00:00"
+ "time": "2021-04-09T13:42:10+00:00"
},
{
"name": "paragonie/random_compat",
},
{
"name": "predis/predis",
- "version": "v1.1.6",
+ "version": "v1.1.7",
"source": {
"type": "git",
"url": "https://github.com/predis/predis.git",
- "reference": "9930e933c67446962997b05201c69c2319bf26de"
+ "reference": "b240daa106d4e02f0c5b7079b41e31ddf66fddf8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/predis/predis/zipball/9930e933c67446962997b05201c69c2319bf26de",
- "reference": "9930e933c67446962997b05201c69c2319bf26de",
+ "url": "https://api.github.com/repos/predis/predis/zipball/b240daa106d4e02f0c5b7079b41e31ddf66fddf8",
+ "reference": "b240daa106d4e02f0c5b7079b41e31ddf66fddf8",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"require-dev": {
- "cweagans/composer-patches": "^1.6",
"phpunit/phpunit": "~4.8"
},
"suggest": {
"ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol"
},
"type": "library",
- "extra": {
- "composer-exit-on-patch-failure": true,
- "patches": {
- "phpunit/phpunit-mock-objects": {
- "Fix PHP 7 and 8 compatibility": "./tests/phpunit_mock_objects.patch"
- },
- "phpunit/phpunit": {
- "Fix PHP 7 compatibility": "./tests/phpunit_php7.patch",
- "Fix PHP 8 compatibility": "./tests/phpunit_php8.patch"
- }
- }
- },
"autoload": {
"psr-4": {
"Predis\\": "src/"
],
"support": {
"issues": "https://github.com/predis/predis/issues",
- "source": "https://github.com/predis/predis/tree/v1.1.6"
+ "source": "https://github.com/predis/predis/tree/v1.1.7"
},
"funding": [
{
"type": "github"
}
],
- "time": "2020-09-11T19:18:05+00:00"
+ "time": "2021-04-04T19:34:46+00:00"
},
{
"name": "psr/container",
},
{
"name": "psr/log",
- "version": "1.1.3",
+ "version": "1.1.4",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc"
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
- "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": ""
},
"require": {
"authors": [
{
"name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"psr-3"
],
"support": {
- "source": "https://github.com/php-fig/log/tree/1.1.3"
+ "source": "https://github.com/php-fig/log/tree/1.1.4"
},
- "time": "2020-03-23T09:12:05+00:00"
+ "time": "2021-05-03T11:20:27+00:00"
},
{
"name": "psr/simple-cache",
},
{
"name": "socialiteproviders/microsoft-azure",
- "version": "4.2.0",
+ "version": "4.2.1",
"source": {
"type": "git",
"url": "https://github.com/SocialiteProviders/Microsoft-Azure.git",
- "reference": "7808764f777a01df88be9ca6b14d683e50aaf88a"
+ "reference": "64779ec21db0bee3111039a67c0fa0ab550a3462"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/SocialiteProviders/Microsoft-Azure/zipball/7808764f777a01df88be9ca6b14d683e50aaf88a",
- "reference": "7808764f777a01df88be9ca6b14d683e50aaf88a",
+ "url": "https://api.github.com/repos/SocialiteProviders/Microsoft-Azure/zipball/64779ec21db0bee3111039a67c0fa0ab550a3462",
+ "reference": "64779ec21db0bee3111039a67c0fa0ab550a3462",
"shasum": ""
},
"require": {
],
"description": "Microsoft Azure OAuth2 Provider for Laravel Socialite",
"support": {
- "source": "https://github.com/SocialiteProviders/Microsoft-Azure/tree/4.2.0"
+ "source": "https://github.com/SocialiteProviders/Microsoft-Azure/tree/4.2.1"
},
- "time": "2020-12-01T23:10:59+00:00"
+ "time": "2021-06-14T22:51:38+00:00"
},
{
"name": "socialiteproviders/okta",
},
{
"name": "socialiteproviders/slack",
- "version": "4.1.0",
+ "version": "4.1.1",
"source": {
"type": "git",
"url": "https://github.com/SocialiteProviders/Slack.git",
- "reference": "8efb25c71d98bedf4010a829d1e41ff9fe449bcc"
+ "reference": "2b781c95daf06ec87a8f3deba2ab613d6bea5e8d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/SocialiteProviders/Slack/zipball/8efb25c71d98bedf4010a829d1e41ff9fe449bcc",
- "reference": "8efb25c71d98bedf4010a829d1e41ff9fe449bcc",
+ "url": "https://api.github.com/repos/SocialiteProviders/Slack/zipball/2b781c95daf06ec87a8f3deba2ab613d6bea5e8d",
+ "reference": "2b781c95daf06ec87a8f3deba2ab613d6bea5e8d",
"shasum": ""
},
"require": {
"ext-json": "*",
- "php": "^7.2|^8.0",
+ "php": "^7.2 || ^8.0",
"socialiteproviders/manager": "~4.0"
},
"type": "library",
],
"description": "Slack OAuth2 Provider for Laravel Socialite",
"support": {
- "source": "https://github.com/SocialiteProviders/Slack/tree/4.1.0"
+ "source": "https://github.com/SocialiteProviders/Slack/tree/4.1.1"
},
- "time": "2020-11-26T17:57:15+00:00"
+ "time": "2021-03-26T04:10:10+00:00"
},
{
"name": "socialiteproviders/twitch",
},
{
"name": "symfony/console",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "c98349bda966c70d6c08b4cd8658377c94166492"
+ "reference": "a62acecdf5b50e314a4f305cd01b5282126f3095"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/c98349bda966c70d6c08b4cd8658377c94166492",
- "reference": "c98349bda966c70d6c08b4cd8658377c94166492",
+ "url": "https://api.github.com/repos/symfony/console/zipball/a62acecdf5b50e314a4f305cd01b5282126f3095",
+ "reference": "a62acecdf5b50e314a4f305cd01b5282126f3095",
"shasum": ""
},
"require": {
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/console/tree/v4.4.20"
+ "source": "https://github.com/symfony/console/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-02-22T18:44:15+00:00"
+ "time": "2021-05-26T11:20:16+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "f907d3e53ecb2a5fad8609eb2f30525287a734c8"
+ "reference": "c1e29de6dc893b130b45d20d8051efbb040560a9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/f907d3e53ecb2a5fad8609eb2f30525287a734c8",
- "reference": "f907d3e53ecb2a5fad8609eb2f30525287a734c8",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/c1e29de6dc893b130b45d20d8051efbb040560a9",
+ "reference": "c1e29de6dc893b130b45d20d8051efbb040560a9",
"shasum": ""
},
"require": {
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v4.4.20"
+ "source": "https://github.com/symfony/css-selector/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-27T09:09:26+00:00"
+ "time": "2021-05-26T17:39:37+00:00"
},
{
"name": "symfony/debug",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
- "reference": "157bbec4fd773bae53c5483c50951a5530a2cc16"
+ "reference": "a8d2d5c94438548bff9f998ca874e202bb29d07f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/157bbec4fd773bae53c5483c50951a5530a2cc16",
- "reference": "157bbec4fd773bae53c5483c50951a5530a2cc16",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/a8d2d5c94438548bff9f998ca874e202bb29d07f",
+ "reference": "a8d2d5c94438548bff9f998ca874e202bb29d07f",
"shasum": ""
},
"require": {
"description": "Provides tools to ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/debug/tree/v4.4.20"
+ "source": "https://github.com/symfony/debug/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-28T16:54:48+00:00"
+ "time": "2021-05-26T17:39:37+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v2.2.0",
+ "version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665"
+ "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665",
- "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
+ "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.2-dev"
+ "dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/master"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2020-09-07T11:33:47+00:00"
+ "time": "2021-03-23T23:28:01+00:00"
},
{
"name": "symfony/error-handler",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "a191550d46b73a527b9d244f185fef439d41cf15"
+ "reference": "310a756cec00d29d89a08518405aded046a54a8b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/a191550d46b73a527b9d244f185fef439d41cf15",
- "reference": "a191550d46b73a527b9d244f185fef439d41cf15",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/310a756cec00d29d89a08518405aded046a54a8b",
+ "reference": "310a756cec00d29d89a08518405aded046a54a8b",
"shasum": ""
},
"require": {
"description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/error-handler/tree/v4.4.20"
+ "source": "https://github.com/symfony/error-handler/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-02-11T08:19:35+00:00"
+ "time": "2021-05-26T17:39:37+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "c352647244bd376bf7d31efbd5401f13f50dad0c"
+ "reference": "047773e7016e4fd45102cedf4bd2558ae0d0c32f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c352647244bd376bf7d31efbd5401f13f50dad0c",
- "reference": "c352647244bd376bf7d31efbd5401f13f50dad0c",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/047773e7016e4fd45102cedf4bd2558ae0d0c32f",
+ "reference": "047773e7016e4fd45102cedf4bd2558ae0d0c32f",
"shasum": ""
},
"require": {
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v4.4.20"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-27T09:09:26+00:00"
+ "time": "2021-05-26T17:39:37+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
},
{
"name": "symfony/finder",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "2543795ab1570df588b9bbd31e1a2bd7037b94f6"
+ "reference": "ed33314396d968a8936c95f5bd1b88bd3b3e94a3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/2543795ab1570df588b9bbd31e1a2bd7037b94f6",
- "reference": "2543795ab1570df588b9bbd31e1a2bd7037b94f6",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/ed33314396d968a8936c95f5bd1b88bd3b3e94a3",
+ "reference": "ed33314396d968a8936c95f5bd1b88bd3b3e94a3",
"shasum": ""
},
"require": {
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v4.4.20"
+ "source": "https://github.com/symfony/finder/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-02-12T10:48:09+00:00"
+ "time": "2021-05-26T11:20:16+00:00"
},
{
"name": "symfony/http-client-contracts",
- "version": "v2.3.1",
+ "version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client-contracts.git",
- "reference": "41db680a15018f9c1d4b23516059633ce280ca33"
+ "reference": "7e82f6084d7cae521a75ef2cb5c9457bbda785f4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/41db680a15018f9c1d4b23516059633ce280ca33",
- "reference": "41db680a15018f9c1d4b23516059633ce280ca33",
+ "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/7e82f6084d7cae521a75ef2cb5c9457bbda785f4",
+ "reference": "7e82f6084d7cae521a75ef2cb5c9457bbda785f4",
"shasum": ""
},
"require": {
},
"type": "library",
"extra": {
- "branch-version": "2.3",
"branch-alias": {
- "dev-main": "2.3-dev"
+ "dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"standards"
],
"support": {
- "source": "https://github.com/symfony/http-client-contracts/tree/v2.3.1"
+ "source": "https://github.com/symfony/http-client-contracts/tree/v2.4.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2020-10-14T17:08:19+00:00"
+ "time": "2021-04-11T23:07:08+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "02d968647fe61b2f419a8dc70c468a9d30a48d3a"
+ "reference": "0c79d5a65ace4fe66e49702658c024a419d2438b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/02d968647fe61b2f419a8dc70c468a9d30a48d3a",
- "reference": "02d968647fe61b2f419a8dc70c468a9d30a48d3a",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0c79d5a65ace4fe66e49702658c024a419d2438b",
+ "reference": "0c79d5a65ace4fe66e49702658c024a419d2438b",
"shasum": ""
},
"require": {
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v4.4.20"
+ "source": "https://github.com/symfony/http-foundation/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-02-25T17:11:33+00:00"
+ "time": "2021-05-26T11:20:16+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "4f36548465489f293b05406f1770492f6efb8adb"
+ "reference": "3795165596fe81a52296b78c9aae938d434069cc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/4f36548465489f293b05406f1770492f6efb8adb",
- "reference": "4f36548465489f293b05406f1770492f6efb8adb",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3795165596fe81a52296b78c9aae938d434069cc",
+ "reference": "3795165596fe81a52296b78c9aae938d434069cc",
"shasum": ""
},
"require": {
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-kernel/tree/v4.4.20"
+ "source": "https://github.com/symfony/http-kernel/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-03-04T18:00:27+00:00"
+ "time": "2021-06-01T07:12:08+00:00"
},
{
"name": "symfony/mime",
- "version": "v5.2.5",
+ "version": "v5.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "554ba128f1955038b45db5e1fa7e93bfc683b139"
+ "reference": "47dd7912152b82d0d4c8d9040dbc93d6232d472a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/554ba128f1955038b45db5e1fa7e93bfc683b139",
- "reference": "554ba128f1955038b45db5e1fa7e93bfc683b139",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/47dd7912152b82d0d4c8d9040dbc93d6232d472a",
+ "reference": "47dd7912152b82d0d4c8d9040dbc93d6232d472a",
"shasum": ""
},
"require": {
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v5.2.5"
+ "source": "https://github.com/symfony/mime/tree/v5.3.2"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-03-07T16:08:20+00:00"
+ "time": "2021-06-09T10:58:01+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.22.1",
+ "version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "c6c942b1ac76c82448322025e084cadc56048b4e"
+ "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e",
- "reference": "c6c942b1ac76c82448322025e084cadc56048b4e",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
+ "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.22-dev"
+ "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-07T16:49:33+00:00"
+ "time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/polyfill-iconv",
- "version": "v1.22.1",
+ "version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-iconv.git",
- "reference": "06fb361659649bcfd6a208a0f1fcaf4e827ad342"
+ "reference": "63b5bb7db83e5673936d6e3b8b3e022ff6474933"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/06fb361659649bcfd6a208a0f1fcaf4e827ad342",
- "reference": "06fb361659649bcfd6a208a0f1fcaf4e827ad342",
+ "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/63b5bb7db83e5673936d6e3b8b3e022ff6474933",
+ "reference": "63b5bb7db83e5673936d6e3b8b3e022ff6474933",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.22-dev"
+ "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-iconv/tree/v1.22.1"
+ "source": "https://github.com/symfony/polyfill-iconv/tree/v1.23.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-22T09:19:47+00:00"
+ "time": "2021-05-27T09:27:20+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
- "version": "v1.22.1",
+ "version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
- "reference": "2d63434d922daf7da8dd863e7907e67ee3031483"
+ "reference": "65bd267525e82759e7d8c4e8ceea44f398838e65"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/2d63434d922daf7da8dd863e7907e67ee3031483",
- "reference": "2d63434d922daf7da8dd863e7907e67ee3031483",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/65bd267525e82759e7d8c4e8ceea44f398838e65",
+ "reference": "65bd267525e82759e7d8c4e8ceea44f398838e65",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.22-dev"
+ "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.22.1"
+ "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.23.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-22T09:19:47+00:00"
+ "time": "2021-05-27T09:27:20+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.22.1",
+ "version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
- "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248"
+ "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/43a0283138253ed1d48d352ab6d0bdb3f809f248",
- "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
+ "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.22-dev"
+ "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-22T09:19:47+00:00"
+ "time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.22.1",
+ "version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "5232de97ee3b75b0360528dae24e73db49566ab1"
+ "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1",
- "reference": "5232de97ee3b75b0360528dae24e73db49566ab1",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
+ "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.22-dev"
+ "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-22T09:19:47+00:00"
+ "time": "2021-05-27T09:27:20+00:00"
},
{
"name": "symfony/polyfill-php72",
- "version": "v1.22.1",
+ "version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
- "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9"
+ "reference": "9a142215a36a3888e30d0a9eeea9766764e96976"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9",
- "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9",
+ "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976",
+ "reference": "9a142215a36a3888e30d0a9eeea9766764e96976",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.22-dev"
+ "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php72/tree/v1.22.1"
+ "source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-07T16:49:33+00:00"
+ "time": "2021-05-27T09:17:38+00:00"
},
{
"name": "symfony/polyfill-php73",
- "version": "v1.22.1",
+ "version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
- "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2"
+ "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2",
- "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010",
+ "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.22-dev"
+ "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1"
+ "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-07T16:49:33+00:00"
+ "time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/polyfill-php80",
- "version": "v1.22.1",
+ "version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91"
+ "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91",
- "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0",
+ "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.22-dev"
+ "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1"
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-07T16:49:33+00:00"
+ "time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/process",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "7e950b6366d4da90292c2e7fa820b3c1842b965a"
+ "reference": "cd61e6dd273975c6625316de9d141ebd197f93c9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/7e950b6366d4da90292c2e7fa820b3c1842b965a",
- "reference": "7e950b6366d4da90292c2e7fa820b3c1842b965a",
+ "url": "https://api.github.com/repos/symfony/process/zipball/cd61e6dd273975c6625316de9d141ebd197f93c9",
+ "reference": "cd61e6dd273975c6625316de9d141ebd197f93c9",
"shasum": ""
},
"require": {
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v4.4.20"
+ "source": "https://github.com/symfony/process/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-27T09:09:26+00:00"
+ "time": "2021-05-26T11:20:16+00:00"
},
{
"name": "symfony/routing",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "69919991c845b34626664ddc9b3aef9d09d2a5df"
+ "reference": "3a3c2f197ad0846ac6413225fc78868ba1c61434"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/69919991c845b34626664ddc9b3aef9d09d2a5df",
- "reference": "69919991c845b34626664ddc9b3aef9d09d2a5df",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/3a3c2f197ad0846ac6413225fc78868ba1c61434",
+ "reference": "3a3c2f197ad0846ac6413225fc78868ba1c61434",
"shasum": ""
},
"require": {
"url"
],
"support": {
- "source": "https://github.com/symfony/routing/tree/v4.4.20"
+ "source": "https://github.com/symfony/routing/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-02-22T15:37:04+00:00"
+ "time": "2021-05-26T17:39:37+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v2.2.0",
+ "version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1"
+ "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1",
- "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
+ "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
- "psr/container": "^1.0"
+ "psr/container": "^1.1"
},
"suggest": {
"symfony/service-implementation": ""
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.2-dev"
+ "dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/master"
+ "source": "https://github.com/symfony/service-contracts/tree/v2.4.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2020-09-07T11:33:47+00:00"
+ "time": "2021-04-01T10:43:52+00:00"
},
{
"name": "symfony/translation",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "2271b6d577018a7dea75a9162a08ac84f8234deb"
+ "reference": "dfe132c5c6d89f90ce7f961742cc532e9ca16dd4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/2271b6d577018a7dea75a9162a08ac84f8234deb",
- "reference": "2271b6d577018a7dea75a9162a08ac84f8234deb",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/dfe132c5c6d89f90ce7f961742cc532e9ca16dd4",
+ "reference": "dfe132c5c6d89f90ce7f961742cc532e9ca16dd4",
"shasum": ""
},
"require": {
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/translation/tree/v4.4.20"
+ "source": "https://github.com/symfony/translation/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-02-26T13:53:48+00:00"
+ "time": "2021-05-26T17:39:37+00:00"
},
{
"name": "symfony/translation-contracts",
- "version": "v2.3.0",
+ "version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation-contracts.git",
- "reference": "e2eaa60b558f26a4b0354e1bbb25636efaaad105"
+ "reference": "95c812666f3e91db75385749fe219c5e494c7f95"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/e2eaa60b558f26a4b0354e1bbb25636efaaad105",
- "reference": "e2eaa60b558f26a4b0354e1bbb25636efaaad105",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95",
+ "reference": "95c812666f3e91db75385749fe219c5e494c7f95",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"standards"
],
"support": {
- "source": "https://github.com/symfony/translation-contracts/tree/v2.3.0"
+ "source": "https://github.com/symfony/translation-contracts/tree/v2.4.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2020-09-28T13:05:58+00:00"
+ "time": "2021-03-23T23:28:01+00:00"
},
{
"name": "symfony/var-dumper",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "a1eab2f69906dc83c5ddba4632180260d0ab4f7f"
+ "reference": "31ea689a8e7d2410016b0d25fc15a1ba05a6e2e0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a1eab2f69906dc83c5ddba4632180260d0ab4f7f",
- "reference": "a1eab2f69906dc83c5ddba4632180260d0ab4f7f",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/31ea689a8e7d2410016b0d25fc15a1ba05a6e2e0",
+ "reference": "31ea689a8e7d2410016b0d25fc15a1ba05a6e2e0",
"shasum": ""
},
"require": {
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v4.4.20"
+ "source": "https://github.com/symfony/var-dumper/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-27T09:09:26+00:00"
+ "time": "2021-05-27T09:48:32+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
"packages-dev": [
{
"name": "barryvdh/laravel-debugbar",
- "version": "v3.5.2",
+ "version": "v3.6.2",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git",
- "reference": "cae0a8d1cb89b0f0522f65e60465e16d738e069b"
+ "reference": "70b89754913fd89fef16d0170a91dbc2a5cd633a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/cae0a8d1cb89b0f0522f65e60465e16d738e069b",
- "reference": "cae0a8d1cb89b0f0522f65e60465e16d738e069b",
+ "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/70b89754913fd89fef16d0170a91dbc2a5cd633a",
+ "reference": "70b89754913fd89fef16d0170a91dbc2a5cd633a",
"shasum": ""
},
"require": {
],
"support": {
"issues": "https://github.com/barryvdh/laravel-debugbar/issues",
- "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.5.2"
+ "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.2"
},
"funding": [
+ {
+ "url": "https://fruitcake.nl",
+ "type": "custom"
+ },
{
"url": "https://github.com/barryvdh",
"type": "github"
}
],
- "time": "2021-01-06T14:21:44+00:00"
+ "time": "2021-06-14T14:29:26+00:00"
},
{
"name": "barryvdh/laravel-ide-helper",
},
{
"name": "composer/ca-bundle",
- "version": "1.2.9",
+ "version": "1.2.10",
"source": {
"type": "git",
"url": "https://github.com/composer/ca-bundle.git",
- "reference": "78a0e288fdcebf92aa2318a8d3656168da6ac1a5"
+ "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/ca-bundle/zipball/78a0e288fdcebf92aa2318a8d3656168da6ac1a5",
- "reference": "78a0e288fdcebf92aa2318a8d3656168da6ac1a5",
+ "url": "https://api.github.com/repos/composer/ca-bundle/zipball/9fdb22c2e97a614657716178093cd1da90a64aa8",
+ "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8",
"shasum": ""
},
"require": {
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/ca-bundle/issues",
- "source": "https://github.com/composer/ca-bundle/tree/1.2.9"
+ "source": "https://github.com/composer/ca-bundle/tree/1.2.10"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-01-12T12:10:35+00:00"
+ "time": "2021-06-07T13:58:28+00:00"
},
{
"name": "composer/composer",
- "version": "2.0.11",
+ "version": "2.1.3",
"source": {
"type": "git",
"url": "https://github.com/composer/composer.git",
- "reference": "a5a5632da0b1c2d6fa9a3b65f1f4e90d1f04abb9"
+ "reference": "fc5c4573aafce3a018eb7f1f8f91cea423970f2e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/composer/zipball/a5a5632da0b1c2d6fa9a3b65f1f4e90d1f04abb9",
- "reference": "a5a5632da0b1c2d6fa9a3b65f1f4e90d1f04abb9",
+ "url": "https://api.github.com/repos/composer/composer/zipball/fc5c4573aafce3a018eb7f1f8f91cea423970f2e",
+ "reference": "fc5c4573aafce3a018eb7f1f8f91cea423970f2e",
"shasum": ""
},
"require": {
"composer/ca-bundle": "^1.0",
+ "composer/metadata-minifier": "^1.0",
"composer/semver": "^3.0",
"composer/spdx-licenses": "^1.2",
- "composer/xdebug-handler": "^1.1",
+ "composer/xdebug-handler": "^2.0",
"justinrainbow/json-schema": "^5.2.10",
"php": "^5.3.2 || ^7.0 || ^8.0",
"psr/log": "^1.0",
"react/promise": "^1.2 || ^2.7",
"seld/jsonlint": "^1.4",
"seld/phar-utils": "^1.0",
- "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0",
- "symfony/filesystem": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0",
- "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0",
- "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0"
+ "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
+ "symfony/filesystem": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
+ "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
+ "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0"
},
"require-dev": {
"phpspec/prophecy": "^1.10",
- "symfony/phpunit-bridge": "^4.2 || ^5.0"
+ "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0"
},
"suggest": {
"ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-master": "2.1-dev"
}
},
"autoload": {
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/composer/issues",
- "source": "https://github.com/composer/composer/tree/2.0.11"
+ "source": "https://github.com/composer/composer/tree/2.1.3"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-06-09T14:31:20+00:00"
+ },
+ {
+ "name": "composer/metadata-minifier",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/metadata-minifier.git",
+ "reference": "c549d23829536f0d0e984aaabbf02af91f443207"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207",
+ "reference": "c549d23829536f0d0e984aaabbf02af91f443207",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2",
+ "phpstan/phpstan": "^0.12.55",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\MetadataMinifier\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Small utility library that handles metadata minification and expansion.",
+ "keywords": [
+ "composer",
+ "compression"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/metadata-minifier/issues",
+ "source": "https://github.com/composer/metadata-minifier/tree/1.0.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-02-24T13:57:23+00:00"
+ "time": "2021-04-07T13:37:33+00:00"
},
{
"name": "composer/semver",
- "version": "3.2.4",
+ "version": "3.2.5",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
- "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464"
+ "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/semver/zipball/a02fdf930a3c1c3ed3a49b5f63859c0c20e10464",
- "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464",
+ "url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9",
+ "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9",
"shasum": ""
},
"require": {
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/semver/issues",
- "source": "https://github.com/composer/semver/tree/3.2.4"
+ "source": "https://github.com/composer/semver/tree/3.2.5"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2020-11-13T08:59:24+00:00"
+ "time": "2021-05-24T12:41:47+00:00"
},
{
"name": "composer/spdx-licenses",
},
{
"name": "composer/xdebug-handler",
- "version": "1.4.5",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
- "reference": "f28d44c286812c714741478d968104c5e604a1d4"
+ "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f28d44c286812c714741478d968104c5e604a1d4",
- "reference": "f28d44c286812c714741478d968104c5e604a1d4",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/964adcdd3a28bf9ed5d9ac6450064e0d71ed7496",
+ "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496",
"shasum": ""
},
"require": {
"psr/log": "^1.0"
},
"require-dev": {
- "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8"
+ "phpstan/phpstan": "^0.12.55",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"autoload": {
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
- "source": "https://github.com/composer/xdebug-handler/tree/1.4.5"
+ "source": "https://github.com/composer/xdebug-handler/tree/2.0.1"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2020-11-13T08:04:11+00:00"
+ "time": "2021-05-05T19:37:51+00:00"
},
{
"name": "doctrine/instantiator",
},
{
"name": "fakerphp/faker",
- "version": "v1.13.0",
+ "version": "v1.14.1",
"source": {
"type": "git",
"url": "https://github.com/FakerPHP/Faker.git",
- "reference": "ab3f5364d01f2c2c16113442fb987d26e4004913"
+ "reference": "ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/ab3f5364d01f2c2c16113442fb987d26e4004913",
- "reference": "ab3f5364d01f2c2c16113442fb987d26e4004913",
+ "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1",
+ "reference": "ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1",
"shasum": ""
},
"require": {
- "php": "^7.1 || ^8.0"
+ "php": "^7.1 || ^8.0",
+ "psr/container": "^1.0",
+ "symfony/deprecation-contracts": "^2.2"
},
"conflict": {
"fzaninotto/faker": "*"
"require-dev": {
"bamarni/composer-bin-plugin": "^1.4.1",
"ext-intl": "*",
- "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.4.2"
+ "symfony/phpunit-bridge": "^4.4 || ^5.2"
+ },
+ "suggest": {
+ "ext-curl": "Required by Faker\\Provider\\Image to download images.",
+ "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.",
+ "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.",
+ "ext-mbstring": "Required for multibyte Unicode string functionality."
},
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "v1.15-dev"
+ }
+ },
"autoload": {
"psr-4": {
"Faker\\": "src/Faker/"
],
"support": {
"issues": "https://github.com/FakerPHP/Faker/issues",
- "source": "https://github.com/FakerPHP/Faker/tree/v1.13.0"
+ "source": "https://github.com/FakerPHP/Faker/tree/v.1.14.1"
},
- "time": "2020-12-18T16:50:48+00:00"
+ "time": "2021-03-30T06:27:33+00:00"
},
{
"name": "hamcrest/hamcrest-php",
},
{
"name": "nikic/php-parser",
- "version": "v4.10.4",
+ "version": "v4.10.5",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e"
+ "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e",
- "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4432ba399e47c66624bc73c8c0f811e5c109576f",
+ "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f",
"shasum": ""
},
"require": {
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.4"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.5"
},
- "time": "2020-12-20T10:01:03+00:00"
+ "time": "2021-05-03T19:11:20+00:00"
},
{
"name": "phar-io/manifest",
},
{
"name": "phpunit/php-code-coverage",
- "version": "9.2.5",
+ "version": "9.2.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1"
+ "reference": "f6293e1b30a2354e8428e004689671b83871edde"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1",
- "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde",
+ "reference": "f6293e1b30a2354e8428e004689671b83871edde",
"shasum": ""
},
"require": {
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.5"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6"
},
"funding": [
{
"type": "github"
}
],
- "time": "2020-11-28T06:44:49+00:00"
+ "time": "2021-03-28T07:26:59+00:00"
},
{
"name": "phpunit/php-file-iterator",
},
{
"name": "phpunit/phpunit",
- "version": "9.5.3",
+ "version": "9.5.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "27241ac75fc37ecf862b6e002bf713b6566cbe41"
+ "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/27241ac75fc37ecf862b6e002bf713b6566cbe41",
- "reference": "27241ac75fc37ecf862b6e002bf713b6566cbe41",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/89ff45ea9d70e35522fb6654a2ebc221158de276",
+ "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276",
"shasum": ""
},
"require": {
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
- "sebastian/type": "^2.3",
+ "sebastian/type": "^2.3.2",
"sebastian/version": "^3.0.2"
},
"require-dev": {
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.3"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.5"
},
"funding": [
{
"type": "github"
}
],
- "time": "2021-03-17T07:30:34+00:00"
+ "time": "2021-06-05T04:49:07+00:00"
},
{
"name": "react/promise",
},
{
"name": "sebastian/global-state",
- "version": "5.0.2",
+ "version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "a90ccbddffa067b51f574dea6eb25d5680839455"
+ "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455",
- "reference": "a90ccbddffa067b51f574dea6eb25d5680839455",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49",
+ "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49",
"shasum": ""
},
"require": {
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
- "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.2"
+ "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3"
},
"funding": [
{
"type": "github"
}
],
- "time": "2020-10-26T15:55:19+00:00"
+ "time": "2021-06-11T13:31:12+00:00"
},
{
"name": "sebastian/lines-of-code",
},
{
"name": "sebastian/type",
- "version": "2.3.1",
+ "version": "2.3.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
- "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2"
+ "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/81cd61ab7bbf2de744aba0ea61fae32f721df3d2",
- "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914",
+ "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914",
"shasum": ""
},
"require": {
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
- "source": "https://github.com/sebastianbergmann/type/tree/2.3.1"
+ "source": "https://github.com/sebastianbergmann/type/tree/2.3.4"
},
"funding": [
{
"type": "github"
}
],
- "time": "2020-10-26T13:18:59+00:00"
+ "time": "2021-06-15T12:49:02+00:00"
},
{
"name": "sebastian/version",
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.5.8",
+ "version": "3.6.0",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "9d583721a7157ee997f235f327de038e7ea6dac4"
+ "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9d583721a7157ee997f235f327de038e7ea6dac4",
- "reference": "9d583721a7157ee997f235f327de038e7ea6dac4",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
+ "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
"shasum": ""
},
"require": {
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
- "time": "2020-10-23T02:01:07+00:00"
+ "time": "2021-04-09T00:54:41+00:00"
},
{
"name": "symfony/dom-crawler",
- "version": "v4.4.20",
+ "version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
- "reference": "be133557f1b0e6672367325b508e65da5513a311"
+ "reference": "41d15bb6d6b95d2be763c514bb2494215d9c5eef"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/be133557f1b0e6672367325b508e65da5513a311",
- "reference": "be133557f1b0e6672367325b508e65da5513a311",
+ "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/41d15bb6d6b95d2be763c514bb2494215d9c5eef",
+ "reference": "41d15bb6d6b95d2be763c514bb2494215d9c5eef",
"shasum": ""
},
"require": {
"description": "Eases DOM navigation for HTML and XML documents",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/dom-crawler/tree/v4.4.20"
+ "source": "https://github.com/symfony/dom-crawler/tree/v4.4.25"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-02-14T12:29:41+00:00"
+ "time": "2021-05-26T11:20:16+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v5.2.4",
+ "version": "v5.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "710d364200997a5afde34d9fe57bd52f3cc1e108"
+ "reference": "348116319d7fb7d1faa781d26a48922428013eb2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/710d364200997a5afde34d9fe57bd52f3cc1e108",
- "reference": "710d364200997a5afde34d9fe57bd52f3cc1e108",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/348116319d7fb7d1faa781d26a48922428013eb2",
+ "reference": "348116319d7fb7d1faa781d26a48922428013eb2",
"shasum": ""
},
"require": {
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v5.2.4"
+ "source": "https://github.com/symfony/filesystem/tree/v5.3.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2021-02-12T10:38:38+00:00"
+ "time": "2021-05-26T17:43:10+00:00"
},
{
"name": "theseer/tokenizer",
"php": "^7.3|^8.0",
"ext-curl": "*",
"ext-dom": "*",
+ "ext-fileinfo": "*",
"ext-gd": "*",
"ext-json": "*",
"ext-mbstring": "*",
{
Schema::create('search_terms', function (Blueprint $table) {
$table->increments('id');
- $table->string('term', 200);
+ $table->string('term', 180);
$table->string('entity_type', 100);
$table->integer('entity_id');
$table->integer('score');
public function up()
{
Schema::table('roles', function (Blueprint $table) {
- $table->string('external_auth_id', 200)->default('');
+ $table->string('external_auth_id', 180)->default('');
$table->index('external_auth_id');
});
}
Schema::create('bookshelves', function (Blueprint $table) {
$table->increments('id');
- $table->string('name', 200);
- $table->string('slug', 200);
+ $table->string('name', 180);
+ $table->string('slug', 180);
$table->text('description');
$table->integer('created_by')->nullable()->default(null);
$table->integer('updated_by')->nullable()->default(null);
public function up()
{
Schema::table('users', function (Blueprint $table) {
- $table->string('slug', 250);
+ $table->string('slug', 180);
});
$slugMap = [];
--- /dev/null
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateFavouritesTable extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create('favourites', function (Blueprint $table) {
+ $table->increments('id');
+ $table->integer('user_id')->index();
+ $table->integer('favouritable_id');
+ $table->string('favouritable_type', 100);
+ $table->timestamps();
+
+ $table->index(['favouritable_id', 'favouritable_type'], 'favouritable_index');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('favourites');
+ }
+}
# Install additional dependacnies and configure apache
RUN apt-get update -y \
- && apt-get install -y git zip unzip libpng-dev libldap2-dev wait-for-it \
+ && apt-get install -y git zip unzip libpng-dev libldap2-dev libzip-dev wait-for-it \
&& docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu \
- && docker-php-ext-install pdo_mysql gd ldap \
+ && docker-php-ext-install pdo_mysql gd ldap zip \
&& a2enmod rewrite \
&& sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \
&& sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
# Use the default production configuration and update it as required
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
- && sed -i 's/memory_limit = 128M/memory_limit = 512M/g' "$PHP_INI_DIR/php.ini"
\ No newline at end of file
+ && sed -i 's/memory_limit = 128M/memory_limit = 512M/g' "$PHP_INI_DIR/php.ini"
'name' => 'Reddit',
], '\SocialiteProviders\Reddit\RedditExtendSocialite@handle');
});
+```
+
+In some cases you may need to customize the driver before it performs a redirect.
+This can be done by providing a callback as a fourth parameter like so:
+
+```php
+Theme::addSocialDriver('reddit', [
+ 'client_id' => 'abc123',
+ 'client_secret' => 'def456789',
+ 'name' => 'Reddit',
+], '\SocialiteProviders\Reddit\RedditExtendSocialite@handle', function($driver) {
+ $driver->with(['prompt' => 'select_account']);
+ $driver->scopes(['open_id']);
+});
```
\ No newline at end of file
{
+ "name": "bookstack",
+ "lockfileVersion": 2,
"requires": true,
- "lockfileVersion": 1,
+ "packages": {
+ "": {
+ "dependencies": {
+ "clipboard": "^2.0.8",
+ "codemirror": "^5.61.1",
+ "dropzone": "^5.9.2",
+ "markdown-it": "^12.0.6",
+ "markdown-it-task-lists": "^2.1.1",
+ "sortablejs": "^1.13.0"
+ },
+ "devDependencies": {
+ "chokidar-cli": "^2.1.0",
+ "esbuild": "0.12.8",
+ "livereload": "^0.9.3",
+ "npm-run-all": "^4.1.5",
+ "punycode": "^2.1.1",
+ "sass": "^1.34.1"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+ "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
+ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
+ "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.4.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.1.2"
+ }
+ },
+ "node_modules/chokidar-cli": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-2.1.0.tgz",
+ "integrity": "sha512-6n21AVpW6ywuEPoxJcLXMA2p4T+SLjWsXKny/9yTWFz0kKxESI3eUylpeV97LylING/27T/RVTY0f2/0QaWq9Q==",
+ "dev": true,
+ "dependencies": {
+ "chokidar": "^3.2.3",
+ "lodash.debounce": "^4.0.8",
+ "lodash.throttle": "^4.1.1",
+ "yargs": "^13.3.0"
+ },
+ "bin": {
+ "chokidar": "index.js"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ }
+ },
+ "node_modules/clipboard": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz",
+ "integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==",
+ "dependencies": {
+ "good-listener": "^1.2.2",
+ "select": "^1.1.2",
+ "tiny-emitter": "^2.0.0"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "node_modules/codemirror": {
+ "version": "5.61.1",
+ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.61.1.tgz",
+ "integrity": "sha512-+D1NZjAucuzE93vJGbAaXzvoBHwp9nJZWWWF9utjv25+5AZUiah6CIlfb4ikG4MoDsFsCG8niiJH5++OO2LgIQ=="
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "dependencies": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "engines": {
+ "node": ">=4.8"
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "dependencies": {
+ "object-keys": "^1.0.12"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/delegate": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
+ "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+ },
+ "node_modules/dropzone": {
+ "version": "5.9.2",
+ "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.9.2.tgz",
+ "integrity": "sha512-5t2z51DzIsWDbTpwcJIvUlwxBbvcwdCApz0yb9ecKJwG155Xm92KMEZmHW1B0MzoXOKvFwdd0nPu5cpeVcvPHQ=="
+ },
+ "node_modules/emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "node_modules/entities": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
+ "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.17.6",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
+ "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
+ "dev": true,
+ "dependencies": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.2.0",
+ "is-regex": "^1.1.0",
+ "object-inspect": "^1.7.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.0",
+ "string.prototype.trimend": "^1.0.1",
+ "string.prototype.trimstart": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.12.8",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.8.tgz",
+ "integrity": "sha512-sx/LwlP/SWTGsd9G4RlOPrXnIihAJ2xwBUmzoqe2nWwbXORMQWtAGNJNYLBJJqa3e9PWvVzxdrtyFZJcr7D87g==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+ "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/good-listener": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
+ "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
+ "dependencies": {
+ "delegate": "^3.1.2"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
+ "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
+ "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
+ "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+ "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "node_modules/json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "node_modules/linkify-it": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz",
+ "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==",
+ "dependencies": {
+ "uc.micro": "^1.0.1"
+ }
+ },
+ "node_modules/livereload": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz",
+ "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==",
+ "dev": true,
+ "dependencies": {
+ "chokidar": "^3.5.0",
+ "livereload-js": "^3.3.1",
+ "opts": ">= 1.2.0",
+ "ws": "^7.4.3"
+ },
+ "bin": {
+ "livereload": "bin/livereload.js"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/livereload-js": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.3.2.tgz",
+ "integrity": "sha512-w677WnINxFkuixAoUEXOStewzLYGI76XVag+0JWMMEyjJQKs0ibWZMxkTlB96Lm3EjZ7IeOxVziBEbtxVQqQZA==",
+ "dev": true
+ },
+ "node_modules/livereload/node_modules/chokidar": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
+ "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.5.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.1"
+ }
+ },
+ "node_modules/livereload/node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/livereload/node_modules/readdirp": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
+ "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
+ "dev": true
+ },
+ "node_modules/lodash.throttle": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+ "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=",
+ "dev": true
+ },
+ "node_modules/markdown-it": {
+ "version": "12.0.6",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.6.tgz",
+ "integrity": "sha512-qv3sVLl4lMT96LLtR7xeRJX11OUFjsaD5oVat2/SNBIb21bJXwal2+SklcRbTwGwqWpWH/HRtYavOoJE+seL8w==",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "~2.1.0",
+ "linkify-it": "^3.0.1",
+ "mdurl": "^1.0.1",
+ "uc.micro": "^1.0.5"
+ },
+ "bin": {
+ "markdown-it": "bin/markdown-it.js"
+ }
+ },
+ "node_modules/markdown-it-task-lists": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz",
+ "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA=="
+ },
+ "node_modules/mdurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
+ },
+ "node_modules/memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "node_modules/normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-all": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+ "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "chalk": "^2.4.1",
+ "cross-spawn": "^6.0.5",
+ "memorystream": "^0.3.1",
+ "minimatch": "^3.0.4",
+ "pidtree": "^0.3.0",
+ "read-pkg": "^3.0.0",
+ "shell-quote": "^1.6.1",
+ "string.prototype.padend": "^3.0.0"
+ },
+ "bin": {
+ "npm-run-all": "bin/npm-run-all/index.js",
+ "run-p": "bin/run-p/index.js",
+ "run-s": "bin/run-s/index.js"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
+ "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
+ "dev": true
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/opts": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz",
+ "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==",
+ "dev": true
+ },
+ "node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "dependencies": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "node_modules/path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/pidtree": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
+ "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
+ "dev": true,
+ "bin": {
+ "pidtree": "bin/pidtree.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+ "dev": true,
+ "dependencies": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
+ "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "node_modules/resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "dependencies": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "node_modules/sass": {
+ "version": "1.34.1",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.34.1.tgz",
+ "integrity": "sha512-scLA7EIZM+MmYlej6sdVr0HRbZX5caX5ofDT9asWnUJj21oqgsC+1LuNfm0eg+vM0fCTZHhwImTiCU0sx9h9CQ==",
+ "dev": true,
+ "dependencies": {
+ "chokidar": ">=3.0.0 <4.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=8.9.0"
+ }
+ },
+ "node_modules/select": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
+ "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
+ },
+ "node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shell-quote": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
+ "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
+ "dev": true
+ },
+ "node_modules/sortablejs": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.13.0.tgz",
+ "integrity": "sha512-RBJirPY0spWCrU5yCmWM1eFs/XgX2J5c6b275/YyxFRgnzPhKl/TDeU2hNR8Dt7ITq66NRPM4UlOt+e5O4CFHg=="
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+ "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "dev": true,
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+ "dev": true
+ },
+ "node_modules/string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/string.prototype.padend": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz",
+ "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0-next.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
+ "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
+ "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/tiny-emitter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+ "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/uc.micro": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "node_modules/wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ws": {
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
+ "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/y18n": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
+ "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
+ "dev": true
+ },
+ "node_modules/yargs": {
+ "version": "13.3.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+ "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.2"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "13.1.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+ "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ },
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
}
},
"argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "requires": {
- "sprintf-js": "~1.0.2"
- }
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"balanced-match": {
"version": "1.0.0",
}
},
"codemirror": {
- "version": "5.60.0",
- "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.60.0.tgz",
- "integrity": "sha512-AEL7LhFOlxPlCL8IdTcJDblJm8yrAGib7I+DErJPdZd4l6imx8IMgKK3RblVgBQqz3TZJR4oknQ03bz+uNjBYA=="
+ "version": "5.61.1",
+ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.61.1.tgz",
+ "integrity": "sha512-+D1NZjAucuzE93vJGbAaXzvoBHwp9nJZWWWF9utjv25+5AZUiah6CIlfb4ikG4MoDsFsCG8niiJH5++OO2LgIQ=="
},
"color-convert": {
"version": "1.9.3",
"dev": true
},
"entities": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
- "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ=="
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
+ "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w=="
},
"error-ex": {
"version": "1.3.2",
}
},
"esbuild": {
- "version": "0.7.8",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.7.8.tgz",
- "integrity": "sha512-6UT1nZB+8ja5avctUC6d3kGOUAhy6/ZYHljL4nk3++1ipadghBhUCAcwsTHsmUvdu04CcGKzo13mE+ZQ2O3zrA==",
+ "version": "0.12.8",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.8.tgz",
+ "integrity": "sha512-sx/LwlP/SWTGsd9G4RlOPrXnIihAJ2xwBUmzoqe2nWwbXORMQWtAGNJNYLBJJqa3e9PWvVzxdrtyFZJcr7D87g==",
"dev": true
},
"escape-string-regexp": {
"dev": true
},
"glob-parent": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
"dev": true
},
"hosted-git-info": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
- "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
"dev": true
},
"is-arrayish": {
"dev": true
},
"markdown-it": {
- "version": "11.0.1",
- "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-11.0.1.tgz",
- "integrity": "sha512-aU1TzmBKcWNNYvH9pjq6u92BML+Hz3h5S/QpfTFwiQF852pLT+9qHsrhM9JYipkOXZxGn+sGH8oyJE9FD9WezQ==",
+ "version": "12.0.6",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.6.tgz",
+ "integrity": "sha512-qv3sVLl4lMT96LLtR7xeRJX11OUFjsaD5oVat2/SNBIb21bJXwal2+SklcRbTwGwqWpWH/HRtYavOoJE+seL8w==",
"requires": {
- "argparse": "^1.0.7",
- "entities": "~2.0.0",
+ "argparse": "^2.0.1",
+ "entities": "~2.1.0",
"linkify-it": "^3.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
}
},
"sass": {
- "version": "1.32.8",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.32.8.tgz",
- "integrity": "sha512-Sl6mIeGpzjIUZqvKnKETfMf0iDAswD9TNlv13A7aAF3XZlRPMq4VvJWBC2N2DXbp94MQVdNSFG6LfF/iOXrPHQ==",
+ "version": "1.34.1",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.34.1.tgz",
+ "integrity": "sha512-scLA7EIZM+MmYlej6sdVr0HRbZX5caX5ofDT9asWnUJj21oqgsC+1LuNfm0eg+vM0fCTZHhwImTiCU0sx9h9CQ==",
"dev": true,
"requires": {
- "chokidar": ">=2.0.0 <4.0.0"
+ "chokidar": ">=3.0.0 <4.0.0"
}
},
"select": {
"integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
"dev": true
},
- "sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
- },
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
}
},
"ws": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz",
- "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==",
- "dev": true
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
+ "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
+ "dev": true,
+ "requires": {}
},
"y18n": {
"version": "4.0.1",
},
"devDependencies": {
"chokidar-cli": "^2.1.0",
- "esbuild": "0.7.8",
+ "esbuild": "0.12.8",
"livereload": "^0.9.3",
"npm-run-all": "^4.1.5",
"punycode": "^2.1.1",
- "sass": "^1.32.8"
+ "sass": "^1.34.1"
},
"dependencies": {
"clipboard": "^2.0.8",
- "codemirror": "^5.60.0",
+ "codemirror": "^5.61.1",
"dropzone": "^5.9.2",
- "markdown-it": "^11.0.1",
+ "markdown-it": "^12.0.6",
"markdown-it-task-lists": "^2.1.1",
"sortablejs": "^1.13.0"
}
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
- <path d="M0 0h24v24H0z" fill="none"/>
<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm4.24 16L12 15.45 7.77 18l1.12-4.81-3.73-3.23 4.92-.42L12 5l1.92 4.53 4.92.42-3.73 3.23L16.23 18z"/>
</svg>
\ No newline at end of file
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"/></svg>
\ No newline at end of file
-<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
- <path d="M0 0h24v24H0z" fill="none"/>
- <path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/>
-</svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24"><path d="M21.41,11.41l-8.83-8.83C12.21,2.21,11.7,2,11.17,2H4C2.9,2,2,2.9,2,4v7.17c0,0.53,0.21,1.04,0.59,1.41l8.83,8.83 c0.78,0.78,2.05,0.78,2.83,0l7.17-7.17C22.2,13.46,22.2,12.2,21.41,11.41z M6.5,8C5.67,8,5,7.33,5,6.5S5.67,5,6.5,5S8,5.67,8,6.5 S7.33,8,6.5,8z"/></svg>
\ No newline at end of file
--- /dev/null
+/**
+ * Attachments List
+ * Adds '?open=true' query to file attachment links
+ * when ctrl/cmd is pressed down.
+ * @extends {Component}
+ */
+class AttachmentsList {
+
+ setup() {
+ this.container = this.$el;
+ this.setupListeners();
+ }
+
+ setupListeners() {
+ const isExpectedKey = (event) => event.key === 'Control' || event.key === 'Meta';
+ window.addEventListener('keydown', event => {
+ if (isExpectedKey(event)) {
+ this.addOpenQueryToLinks();
+ }
+ }, {passive: true});
+ window.addEventListener('keyup', event => {
+ if (isExpectedKey(event)) {
+ this.removeOpenQueryFromLinks();
+ }
+ }, {passive: true});
+ }
+
+ addOpenQueryToLinks() {
+ const links = this.container.querySelectorAll('a.attachment-file');
+ for (const link of links) {
+ if (link.href.split('?')[1] !== 'open=true') {
+ link.href = link.href + '?open=true';
+ link.setAttribute('target', '_blank');
+ }
+ }
+ }
+
+ removeOpenQueryFromLinks() {
+ const links = this.container.querySelectorAll('a.attachment-file');
+ for (const link of links) {
+ link.href = link.href.split('?')[0];
+ link.removeAttribute('target');
+ }
+ }
+}
+
+export default AttachmentsList;
\ No newline at end of file
this.menu = this.$refs.menu;
this.toggle = this.$refs.toggle;
this.moveMenu = this.$opts.moveMenu;
+ this.bubbleEscapes = this.$opts.bubbleEscapes === 'true';
this.direction = (document.dir === 'rtl') ? 'right' : 'left';
this.body = document.body;
} else if (event.key === 'Escape') {
this.hide();
this.toggle.focus();
- event.stopPropagation();
+ if (!this.bubbleEscapes) {
+ event.stopPropagation();
+ }
}
};
this.container.addEventListener('keydown', keyboardNavigation);
class HeaderMobileToggle {
- constructor(elem) {
- this.elem = elem;
- this.toggleButton = elem.querySelector('.mobile-menu-toggle');
- this.menu = elem.querySelector('.header-links');
- this.open = false;
+ setup() {
+ this.elem = this.$el;
+ this.toggleButton = this.$refs.toggle;
+ this.menu = this.$refs.menu;
+ this.open = false;
this.toggleButton.addEventListener('click', this.onToggle.bind(this));
this.onWindowClick = this.onWindowClick.bind(this);
+ this.onKeyDown = this.onKeyDown.bind(this);
}
onToggle(event) {
this.open = !this.open;
this.menu.classList.toggle('show', this.open);
+ this.toggleButton.setAttribute('aria-expanded', this.open ? 'true' : 'false');
if (this.open) {
+ this.elem.addEventListener('keydown', this.onKeyDown);
window.addEventListener('click', this.onWindowClick)
} else {
+ this.elem.removeEventListener('keydown', this.onKeyDown);
window.removeEventListener('click', this.onWindowClick)
}
event.stopPropagation();
}
+ onKeyDown(event) {
+ if (event.code === 'Escape') {
+ this.onToggle(event);
+ }
+ }
+
onWindowClick(event) {
this.onToggle(event);
}
}
-module.exports = HeaderMobileToggle;
\ No newline at end of file
+export default HeaderMobileToggle;
\ No newline at end of file
import ajaxDeleteRow from "./ajax-delete-row.js"
import ajaxForm from "./ajax-form.js"
import attachments from "./attachments.js"
+import attachmentsList from "./attachments-list.js"
import autoSuggest from "./auto-suggest.js"
import backToTop from "./back-to-top.js"
import bookSort from "./book-sort.js"
"ajax-delete-row": ajaxDeleteRow,
"ajax-form": ajaxForm,
"attachments": attachments,
+ "attachments-list": attachmentsList,
"auto-suggest": autoSuggest,
"back-to-top": backToTop,
"book-sort": bookSort,
this.pageId = this.$opts.pageId;
this.textDirection = this.$opts.textDirection;
this.imageUploadErrorText = this.$opts.imageUploadErrorText;
+ this.serverUploadLimitText = this.$opts.serverUploadLimitText;
this.markdown = new MarkdownIt({html: true});
this.markdown.use(mdTasksLists, {label: true});
this.insertDrawing(resp.data, cursorPos);
DrawIO.close();
}).catch(err => {
- window.$events.emit('error', trans('errors.image_upload_error'));
- console.log(err);
+ this.handleDrawingUploadError(err);
});
});
}
this.cm.focus();
DrawIO.close();
}).catch(err => {
- window.$events.emit('error', this.imageUploadErrorText);
- console.log(err);
+ this.handleDrawingUploadError(err);
});
});
}
+ handleDrawingUploadError(error) {
+ if (error.status === 413) {
+ window.$events.emit('error', this.serverUploadLimitText);
+ } else {
+ window.$events.emit('error', this.imageUploadErrorText);
+ }
+ console.log(error);
+ }
+
// Make the editor full screen
actionFullScreen() {
const alreadyFullscreen = this.elem.classList.contains('fullscreen');
class TriLayout {
- constructor(elem) {
- this.elem = elem;
+ setup() {
+ this.container = this.$refs.container;
+ this.tabs = this.$manyRefs.tab;
this.lastLayoutType = 'none';
this.onDestroy = null;
}
setupMobile() {
- const layoutTabs = document.querySelectorAll('[tri-layout-mobile-tab]');
- for (let tab of layoutTabs) {
+ for (const tab of this.tabs) {
tab.addEventListener('click', this.mobileTabClick);
}
this.onDestroy = () => {
- for (let tab of layoutTabs) {
+ for (const tab of this.tabs) {
tab.removeEventListener('click', this.mobileTabClick);
}
}
* @param event
*/
mobileTabClick(event) {
- const tab = event.target.getAttribute('tri-layout-mobile-tab');
+ const tab = event.target.dataset.tab;
this.showTab(tab);
}
/**
* Show the given tab
- * @param tabName
+ * @param {String} tabName
+ * @param {Boolean }scroll
*/
showTab(tabName, scroll = true) {
this.scrollCache[this.lastTabShown] = document.documentElement.scrollTop;
// Set tab status
- const tabs = document.querySelectorAll('.tri-layout-mobile-tab');
- for (let tab of tabs) {
- const isActive = (tab.getAttribute('tri-layout-mobile-tab') === tabName);
- tab.classList.toggle('active', isActive);
+ for (const tab of this.tabs) {
+ const isActive = (tab.dataset.tab === tabName);
+ tab.setAttribute('aria-selected', isActive ? 'true' : 'false');
}
// Toggle section
const showInfo = (tabName === 'info');
- this.elem.classList.toggle('show-info', showInfo);
+ this.container.classList.toggle('show-info', showInfo);
// Set the scroll position from cache
if (scroll) {
return;
}
- let lang = selectedNode.hasAttribute('data-lang') ? selectedNode.getAttribute('data-lang') : '';
- let currentCode = selectedNode.querySelector('textarea').textContent;
+ const lang = selectedNode.hasAttribute('data-lang') ? selectedNode.getAttribute('data-lang') : '';
+ const currentCode = selectedNode.querySelector('textarea').textContent;
window.components.first('code-editor').open(currentCode, lang, (code, lang) => {
const editorElem = selectedNode.querySelector('.CodeMirror');
return elem.contentEditable !== "false";
});
- if (!codeSamples.length) return;
- editor.undoManager.transact(function () {
- codeSamples.each((index, elem) => {
- Code.wysiwygView(elem);
- });
+ codeSamples.each((index, elem) => {
+ Code.wysiwygView(elem);
});
}
editor.on('init', function() {
// Parse code mirror instances on init, but delay a little so this runs after
// initial styles are fetched into the editor.
- parseCodeMirrorInstances();
+ editor.undoManager.transact(function () {
+ parseCodeMirrorInstances();
+ });
// Parsed code mirror blocks when content is set but wait before setting this handler
// to avoid any init 'SetContent' events.
setTimeout(() => {
- editor.on('SetContent', parseCodeMirrorInstances);
+ editor.on('SetContent', () => {
+ setTimeout(parseCodeMirrorInstances, 100);
+ });
}, 200);
});
const id = "image-" + Math.random().toString(16).slice(2);
const loadingImage = window.baseUrl('/loading.gif');
+ const handleUploadError = (error) => {
+ if (error.status === 413) {
+ window.$events.emit('error', wysiwygComponent.serverUploadLimitText);
+ } else {
+ window.$events.emit('error', wysiwygComponent.imageUploadErrorText);
+ }
+ console.log(error);
+ };
+
// Handle updating an existing image
if (currentNode) {
DrawIO.close();
pageEditor.dom.setAttrib(imgElem, 'src', img.url);
pageEditor.dom.setAttrib(currentNode, 'drawio-diagram', img.id);
} catch (err) {
- window.$events.emit('error', wysiwygComponent.imageUploadErrorText);
- console.log(err);
+ handleUploadError(err);
}
return;
}
pageEditor.dom.get(id).parentNode.setAttribute('drawio-diagram', img.id);
} catch (err) {
pageEditor.dom.remove(id);
- window.$events.emit('error', wysiwygComponent.imageUploadErrorText);
- console.log(err);
+ handleUploadError(err);
}
}, 5);
}
this.pageId = this.$opts.pageId;
this.textDirection = this.$opts.textDirection;
this.imageUploadErrorText = this.$opts.imageUploadErrorText;
+ this.serverUploadLimitText = this.$opts.serverUploadLimitText;
this.isDarkMode = document.documentElement.classList.contains('dark-mode');
this.plugins = "image imagetools table textcolor paste link autolink fullscreen code customhr autosave lists codeeditor media";
let iFrame = null;
-
+let lastApprovedOrigin;
let onInit, onSave;
/**
iFrame.setAttribute('class', 'fullscreen');
iFrame.style.backgroundColor = '#FFFFFF';
document.body.appendChild(iFrame);
+ lastApprovedOrigin = (new URL(drawioUrl)).origin;
}
function close() {
drawEventClose();
}
+/**
+ * Receive and handle a message event from the draw.io window.
+ * @param {MessageEvent} event
+ */
function drawReceive(event) {
if (!event.data || event.data.length < 1) return;
- let message = JSON.parse(event.data);
+ if (event.origin !== lastApprovedOrigin) return;
+
+ const message = JSON.parse(event.data);
if (message.event === 'init') {
drawEventInit();
} else if (message.event === 'exit') {
}
function drawPostMessage(data) {
- iFrame.contentWindow.postMessage(JSON.stringify(data), '*');
+ iFrame.contentWindow.postMessage(JSON.stringify(data), lastApprovedOrigin);
}
async function upload(imageData, pageUploadedToId) {
return null;
}
- const responseContentType = response.headers.get('Content-Type');
- const subType = responseContentType.split('/').pop();
+ const responseContentType = response.headers.get('Content-Type') || '';
+ const subType = responseContentType.split(';')[0].split('/').pop();
if (subType === 'javascript' || subType === 'json') {
return await response.json();
'book_delete' => 'تم حذف الكتاب',
'book_delete_notification' => 'تم حذف الكتاب بنجاح',
'book_sort' => 'تم سرد الكتاب',
- 'book_sort_notification' => 'تÙ\85ت إعادة سرد الكتاب بنجاح',
+ 'book_sort_notification' => 'Ø£Ù\8fعÙ\90Ù\8aدÙ\8e سرد الكتاب بنجاح',
// Bookshelves
'bookshelf_create' => 'تم إنشاء رف الكتب',
'bookshelf_delete' => 'تم تحديث الرف',
'bookshelf_delete_notification' => 'تم حذف الرف بنجاح',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'تم التعليق',
'permissions_update' => 'تحديث الأذونات',
'reset_password_success' => 'تمت استعادة كلمة المرور بنجاح.',
'email_reset_subject' => 'استعد كلمة المرور الخاصة بتطبيق :appName',
'email_reset_text' => 'تم إرسال هذه الرسالة بسبب تلقينا لطلب استعادة كلمة المرور الخاصة بحسابكم.',
- 'email_reset_not_requested' => 'إذا لم يتم طلب استعادة كلمة المرور من قبلكم, فلا حاجة لاتخاذ أية خطوات.',
+ 'email_reset_not_requested' => 'إذا لم يتم طلب استعادة كلمة المرور من قبلكم، فلا حاجة لاتخاذ أية خطوات.',
// Email Confirmation
'email_not_confirmed' => 'لم يتم تأكيد البريد الإلكتروني',
'email_not_confirmed_text' => 'لم يتم بعد تأكيد عنوان البريد الإلكتروني.',
'email_not_confirmed_click_link' => 'الرجاء الضغط على الرابط المرسل إلى بريدكم الإلكتروني بعد تسجيلكم.',
- 'email_not_confirmed_resend' => 'إذا لم يتم إيجاد الرسالة, بإمكانكم إعادة إرسال رسالة التأكيد عن طريق تعبئة النموذج أدناه.',
+ 'email_not_confirmed_resend' => 'إذا لم يتم إيجاد الرسالة، بإمكانكم إعادة إرسال رسالة التأكيد عن طريق تعبئة النموذج أدناه.',
'email_not_confirmed_resend_button' => 'إعادة إرسال رسالة التأكيد',
// User Invite
- 'user_invite_email_subject' => 'تم دعوتك للإنضمام إلى صفحة الحالة الخاصة بـ :app_name!',
+ 'user_invite_email_subject' => 'تمت دعوتك للانضمام إلى صفحة الحالة الخاصة بـ :app_name!',
'user_invite_email_greeting' => 'تم إنشاء حساب مستخدم لك على %site%.',
'user_invite_email_text' => 'انقر على الزر أدناه لتعيين كلمة مرور الحساب والحصول على الوصول:',
'user_invite_email_action' => 'كلمة سر المستخدم',
'remove' => 'إزالة',
'add' => 'إضافة',
'fullscreen' => 'شاشة كاملة',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
- 'sort_options' => 'خيارات الترتيب',
- 'sort_direction_toggle' => 'الترتيب وفق الإتجاه',
+ 'sort_options' => 'خيارات الفرز',
+ 'sort_direction_toggle' => 'الفرز وفق الاتجاه',
'sort_ascending' => 'فرز تصاعدي',
'sort_descending' => 'فرز تنازلي',
'sort_name' => 'الاسم',
- 'sort_default' => 'Default',
+ 'sort_default' => 'افتراضي',
'sort_created_at' => 'تاريخ الإنشاء',
'sort_updated_at' => 'تاريخ التحديث',
// Misc
- 'deleted_user' => 'ØØ°Ù\81 Ù\85ستخدÙ\85',
+ 'deleted_user' => 'اÙ\84Ù\85ستخدÙ\85 اÙ\84Ù\85ØØ°Ù\88Ù\81',
'no_activity' => 'لا يوجد نشاط لعرضه',
'no_items' => 'لا توجد عناصر متوفرة',
- 'back_to_top' => 'العودة للبداية',
+ 'back_to_top' => 'العودة إلى الأعلى',
'toggle_details' => 'عرض / إخفاء التفاصيل',
'toggle_thumbnails' => 'عرض / إخفاء الصور المصغرة',
'details' => 'التفاصيل',
'breadcrumb' => 'شريط التنقل',
// Header
+ 'header_menu_expand' => 'عرض القائمة',
'profile_menu' => 'قائمة ملف التعريف',
'view_profile' => 'عرض الملف الشخصي',
'edit_profile' => 'تعديل الملف الشخصي',
// Layout tabs
'tab_info' => 'معلومات',
+ 'tab_info_label' => 'تبويب: إظهار المعلومات الثانوية',
'tab_content' => 'المحتوى',
+ 'tab_content_label' => 'تبويب: إظهار المحتوى الأساسي',
// Email Content
- 'email_action_help' => 'إذا Ù\88اجÙ\87تÙ\83Ù\85 Ù\85Ø´Ù\83Ù\84Ø© بضغط زر ":actionText" فبإمكانكم نسخ الرابط أدناه ولصقه بالمتصفح:',
+ 'email_action_help' => 'إذا Ù\88اجÙ\87تÙ\83Ù\85 Ù\85Ø´Ù\83Ù\84Ø© عÙ\86د ضغط زر ":actionText" فبإمكانكم نسخ الرابط أدناه ولصقه بالمتصفح:',
'email_rights' => 'جميع الحقوق محفوظة',
// Footer Link Options
// Not directly used but available for convenience to users.
- 'privacy_policy' => 'Privacy Policy',
- 'terms_of_service' => 'Terms of Service',
+ 'privacy_policy' => 'سياسة الخصوصية',
+ 'terms_of_service' => 'اتفاقية شروط الخدمة',
];
'image_load_more' => 'المزيد',
'image_image_name' => 'اسم الصورة',
'image_delete_used' => 'هذه الصورة مستخدمة بالصفحات أدناه.',
- 'image_delete_confirm_text' => 'هل أنت متأكد من أنك تريد حذف هذه الصورة ؟',
+ 'image_delete_confirm_text' => 'هل أنت متأكد من أنك تريد حذف هذه الصورة؟',
'image_select_image' => 'تحديد الصورة',
'image_dropzone' => 'قم بإسقاط الصورة أو اضغط هنا للرفع',
'images_deleted' => 'تم حذف الصور',
'recently_updated_pages' => 'صفحات حُدثت مؤخراً',
'recently_created_chapters' => 'فصول أنشئت مؤخراً',
'recently_created_books' => 'كتب أنشئت مؤخراً',
- 'recently_created_shelves' => 'اÙ\84أرÙ\81Ù\81 اÙ\84Ù\85Ù\86شأة مؤخراً',
+ 'recently_created_shelves' => 'أرÙ\81Ù\81 Ø£Ù\86شئت مؤخراً',
'recently_update' => 'حُدثت مؤخراً',
'recently_viewed' => 'عُرضت مؤخراً',
'recent_activity' => 'نشاطات حديثة',
'images' => 'صور',
'my_recent_drafts' => 'مسوداتي الحديثة',
'my_recently_viewed' => 'ما عرضته مؤخراً',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'لم تستعرض أي صفحات',
- 'no_pages_recently_created' => 'لم يتم إنشاء أي صفحات مؤخراً',
- 'no_pages_recently_updated' => 'لم يتم تحديث أي صفحات مؤخراً',
+ 'no_pages_recently_created' => 'لم تنشأ أي صفحات مؤخراً',
+ 'no_pages_recently_updated' => 'لم تُحدّث أي صفحات مؤخراً',
'export' => 'تصدير',
'export_html' => 'صفحة ويب',
'export_pdf' => 'ملف PDF',
// Permissions and restrictions
'permissions' => 'الأذونات',
- 'permissions_intro' => 'في حال التفعيل, ستتم تبدية هذه الأذونات على أذونات الأدوار.',
+ 'permissions_intro' => 'عند التفعيل، سوف تأخذ هذه الأذونات أولوية على أي صلاحية أخرى للدور.',
'permissions_enable' => 'تفعيل الأذونات المخصصة',
'permissions_save' => 'حفظ الأذونات',
'permissions_owner' => 'Owner',
'search_exact_matches' => 'نتائج مطابقة تماماً',
'search_tags' => 'بحث الوسوم',
'search_options' => 'الخيارات',
- 'search_viewed_by_me' => 'تÙ\85 استعراضÙ\87ا من قبلي',
- 'search_not_viewed_by_me' => 'لم يتم استعراضها من قبلي',
+ 'search_viewed_by_me' => 'استعرضت من قبلي',
+ 'search_not_viewed_by_me' => 'لم تستعرض من قبلي',
'search_permissions_set' => 'حزمة الأذونات',
'search_created_by_me' => 'أنشئت بواسطتي',
'search_updated_by_me' => 'حُدثت بواسطتي',
'shelves' => 'الأرفف',
'x_shelves' => ':count رف|:count أرفف',
'shelves_long' => 'أرفف الكتب',
- 'shelves_empty' => 'لم يتم إنشاء أي أرفف',
+ 'shelves_empty' => 'لم ينشأ أي رف',
'shelves_create' => 'إنشاء رف جديد',
- 'shelves_popular' => 'أرÙ\81Ù\81 شعبÙ\8aة',
+ 'shelves_popular' => 'أرÙ\81Ù\81 رائجة',
'shelves_new' => 'أرفف جديدة',
'shelves_new_action' => 'رف جديد',
'shelves_popular_empty' => 'ستظهر هنا الأرفف الأكثر رواجًا.',
- 'shelves_new_empty' => 'ستظÙ\87ر Ù\87Ù\86ا اÙ\84أرÙ\81Ù\81 اÙ\84تÙ\8a تÙ\85 Ø¥Ù\86شاؤÙ\87ا مؤخرًا.',
+ 'shelves_new_empty' => 'ستظÙ\87ر Ù\87Ù\86ا اÙ\84أرÙ\81Ù\81 اÙ\84تÙ\8a Ø£Ù\86شئت مؤخرًا.',
'shelves_save' => 'حفظ الرف',
'shelves_books' => 'كتب على هذا الرف',
'shelves_add_books' => 'إضافة كتب لهذا الرف',
- 'shelves_drag_books' => 'Ø§Ø³ØØ¨ اÙ\84Ù\83تب Ù\87Ù\86ا Ù\84إضاÙ\81تÙ\87ا Ù\84هذا الرف',
+ 'shelves_drag_books' => 'Ø§Ø³ØØ¨ اÙ\84Ù\83تب Ù\87Ù\86ا Ù\84إضاÙ\81تÙ\87ا Ù\81Ù\8a هذا الرف',
'shelves_empty_contents' => 'لا توجد كتب مخصصة لهذا الرف',
'shelves_edit_and_assign' => 'تحرير الرف لإدراج كتب',
- 'shelves_edit_named' => 'تحرير رف الكتب: الاسم',
+ 'shelves_edit_named' => 'تحرير رف الكتب :name',
'shelves_edit' => 'تحرير رف الكتب',
'shelves_delete' => 'حذف رف الكتب',
- 'shelves_delete_named' => 'حذف رف الكتب: الاسم',
- 'shelves_delete_explain' => "سيؤدي هذا إلى حذف رف الكتب مع الاسم ':المُسمى به'. لن يتم حذف الكتب المتضمنة.",
+ 'shelves_delete_named' => 'حذف رف الكتب :name',
+ 'shelves_delete_explain' => "سيؤدي هذا إلى حذف رف الكتب المسمى ':name'، ولن تحذف الكتب المتضمنة فيه.",
'shelves_delete_confirmation' => 'هل أنت متأكد من أنك تريد حذف هذا الرف؟',
'shelves_permissions' => 'أذونات رف الكتب',
'shelves_permissions_updated' => 'تم تحديث أذونات رف الكتب',
'shelves_copy_permissions_to_books' => 'نسخ أذونات الوصول إلى الكتب',
'shelves_copy_permissions' => 'نسخ الأذونات',
'shelves_copy_permissions_explain' => 'سيؤدي هذا إلى تطبيق إعدادات الأذونات الحالية لهذا الرف على جميع الكتب المتضمنة فيه. قبل التفعيل، تأكد من حفظ أي تغييرات في أذونات هذا الرف.',
- 'shelves_copy_permission_success' => 'تم نسخ أذونات رف الكتب إلى: عد الكتب',
+ 'shelves_copy_permission_success' => 'تم نسخ أذونات رف الكتب إلى :count books',
// Books
'book' => 'كتاب',
'books_create' => 'إنشاء كتاب جديد',
'books_delete' => 'حذف الكتاب',
'books_delete_named' => 'حذف كتاب :bookName',
- 'books_delete_explain' => 'سيتم حذف كتاب \':bookName\'. ستتم إزالة جميع الفصول والصفحات.',
+ 'books_delete_explain' => 'سيتم حذف كتاب \':bookName\'، وأيضا حذف جميع الفصول والصفحات.',
'books_delete_confirmation' => 'تأكيد حذف الكتاب؟',
'books_edit' => 'تعديل الكتاب',
'books_edit_named' => 'تعديل كتاب :bookName',
'pages_revisions_created_by' => 'أنشئ بواسطة',
'pages_revisions_date' => 'تاريخ المراجعة',
'pages_revisions_number' => '#',
- 'pages_revisions_numbered' => 'مراجعة #: رقم تعريفي',
+ 'pages_revisions_numbered' => 'مراجعة #:id',
'pages_revisions_numbered_changes' => 'مراجعة #: رقم تعريفي التغييرات',
'pages_revisions_changelog' => 'سجل التعديل',
'pages_revisions_changes' => 'التعديلات',
'pages_permissions_active' => 'أذونات الصفحة مفعلة',
'pages_initial_revision' => 'نشر مبدئي',
'pages_initial_name' => 'صفحة جديدة',
- 'pages_editing_draft_notification' => 'جار تعديل مسودة لم يتم حفظها من :timeDiff.',
+ 'pages_editing_draft_notification' => 'جارٍ تعديل مسودة لم يتم حفظها من :timeDiff.',
'pages_draft_edited_notification' => 'تم تحديث هذه الصفحة منذ ذلك الوقت. من الأفضل التخلص من هذه المسودة.',
'pages_draft_edit_active' => [
'start_a' => ':count من المستخدمين بدأوا بتعديل هذه الصفحة',
'time_b' => 'في آخر :minCount دقيقة/دقائق',
'message' => 'وقت البدء: احرص على عدم الكتابة فوق تحديثات بعضنا البعض!',
],
- 'pages_draft_discarded' => 'تم التخلص من المسودة. تم تحديث المحرر بمحتوى الصفحة الحالي',
+ 'pages_draft_discarded' => 'تم التخلص من المسودة وتحديث المحرر بمحتوى الصفحة الحالي',
'pages_specific' => 'صفحة محددة',
'pages_is_template' => 'قالب الصفحة',
'tags_remove' => 'إزالة هذه العلامة',
'attachments' => 'المرفقات',
'attachments_explain' => 'ارفع بعض الملفات أو أرفق بعض الروابط لعرضها بصفحتك. ستكون الملفات والروابط معروضة في الشريط الجانبي للصفحة.',
- 'attachments_explain_instant_save' => 'سÙ\8aتÙ\85 ØÙ\81ظ اÙ\84تغÙ\8aÙ\8aرات Ù\87Ù\86ا بÙ\84ØØ¸ØªÙ\87ا',
+ 'attachments_explain_instant_save' => 'سÙ\8aتÙ\85 ØÙ\81ظ اÙ\84تغÙ\8aÙ\8aرات Ù\87Ù\86ا Ø¢Ù\86Ù\8aا.',
'attachments_items' => 'العناصر المرفقة',
'attachments_upload' => 'رفع ملف',
'attachments_link' => 'إرفاق رابط',
'attachments_set_link' => 'تحديد الرابط',
'attachments_delete' => 'هل أنت متأكد من أنك تريد حذف هذا المرفق؟',
'attachments_dropzone' => 'أسقط الملفات أو اضغط هنا لإرفاق ملف',
- 'attachments_no_files' => 'لم يتم رفع أي ملفات',
+ 'attachments_no_files' => 'لم تُرفع أي ملفات',
'attachments_explain_link' => 'بالإمكان إرفاق رابط في حال عدم تفضيل رفع ملف. قد يكون الرابط لصفحة أخرى أو لملف في أحد خدمات التخزين السحابي.',
'attachments_link_name' => 'اسم الرابط',
'attachment_link' => 'رابط المرفق',
'templates_prepend_content' => 'بادئة محتوى الصفحة',
// Profile View
- 'profile_user_for_x' => 'المستخدم لـ : الوقت',
+ 'profile_user_for_x' => 'المستخدم لـ :time',
'profile_created_content' => 'المحتوى المنشأ',
'profile_not_created_pages' => 'لم يتم إنشاء أي صفحات بواسطة :userName',
'profile_not_created_chapters' => 'لم يتم إنشاء أي فصول بواسطة :userName',
'comments' => 'تعليقات',
'comment_add' => 'إضافة تعليق',
'comment_placeholder' => 'ضع تعليقاً هنا',
- 'comment_count' => '{0} ا توجد تعليقات|{1} تعليق واحد|{2} تعليقان|[3,*] :count تعليقات',
+ 'comment_count' => '{0} لا توجد تعليقات|{1} تعليق واحد|{2} تعليقان[3,*] :count تعليقات',
'comment_save' => 'حفظ التعليق',
'comment_saving' => 'جار حفظ التعليق...',
'comment_deleting' => 'جار حذف التعليق...',
'comment_in_reply_to' => 'رداً على :commentId',
// Revision
- 'revision_delete_confirm' => 'هل أنت متأكد من أنك تريد حذف هذا الإصدار؟',
- 'revision_restore_confirm' => 'هل أنت متأكد من أنك تريد استعادة هذا الإصدار؟ سيتم استبدال محتوى الصفحة الحالية.',
- 'revision_delete_success' => 'تم حذف الإصدار',
- 'revision_cannot_delete_latest' => 'لايمكن حذف آخر إصدار.'
+ 'revision_delete_confirm' => 'هل أنت متأكد من أنك تريد حذف هذه المراجعة؟',
+ 'revision_restore_confirm' => 'هل أنت متأكد من أنك تريد استعادة هذه المراجعة؟ سيتم استبدال محتوى الصفحة الحالية.',
+ 'revision_delete_success' => 'تم حذف المراجعة',
+ 'revision_cannot_delete_latest' => 'لايمكن حذف آخر مراجعة.'
];
'404_page_not_found' => 'لم يتم العثور على الصفحة',
'sorry_page_not_found' => 'عفواً, لا يمكن العثور على الصفحة التي تبحث عنها.',
'sorry_page_not_found_permission_warning' => 'إذا كنت تتوقع أن تكون هذه الصفحة موجودة، قد لا يكون لديك تصريح بمشاهدتها.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'العودة للصفحة الرئيسية',
'error_occurred' => 'حدث خطأ',
'app_down' => ':appName لا يعمل حالياً',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'изтрит рафт',
'bookshelf_delete_notification' => 'Рафтът беше успешно изтрит',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'коментирано на',
'permissions_update' => 'updated permissions',
'copy' => 'Копирай',
'reply' => 'Отговори',
'delete' => 'Изтрий',
- 'delete_confirm' => 'Confirm Deletion',
+ 'delete_confirm' => 'Потвърдете изтриването',
'search' => 'Търси',
'search_clear' => 'Изчисти търсенето',
'reset' => 'Нулирай',
'remove' => 'Премахване',
'add' => 'Добави',
'fullscreen' => 'Пълен екран',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Опции за сортиране',
'breadcrumb' => 'Трасиране',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Профил меню',
'view_profile' => 'Разглеждане на профил',
'edit_profile' => 'Редактиране на профила',
// Layout tabs
'tab_info' => 'Информация',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Съдържание',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Ако имате проблеми с бутона ":actionText" по-горе, копирайте и поставете URL адреса по-долу в уеб браузъра си:',
// Footer Link Options
// Not directly used but available for convenience to users.
- 'privacy_policy' => 'Privacy Policy',
- 'terms_of_service' => 'Terms of Service',
+ 'privacy_policy' => 'Лични данни',
+ 'terms_of_service' => 'Общи условия',
];
'image_load_more' => 'Зареди повече',
'image_image_name' => 'Име на изображението',
'image_delete_used' => 'Това изображение е използвано в страницата по-долу.',
- 'image_delete_confirm_text' => 'Are you sure you want to delete this image?',
+ 'image_delete_confirm_text' => 'Сигурни ли сте, че искате да изтриете това изображение?',
'image_select_image' => 'Изберете изображение',
'image_dropzone' => 'Поставете тук изображение или кликнете тук за да качите',
'images_deleted' => 'Изображението е изтрито',
'meta_created_name' => 'Създадено преди :timeLength от :user',
'meta_updated' => 'Актуализирано :timeLength',
'meta_updated_name' => 'Актуализирано преди :timeLength от :user',
- 'meta_owned_name' => 'Owned by :user',
+ 'meta_owned_name' => 'Притежавано от :user',
'entity_select' => 'Избор на обект',
'images' => 'Изображения',
'my_recent_drafts' => 'Моите скорошни драфтове',
'my_recently_viewed' => 'Моите скорошни преглеждания',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'Моите фаворити',
'no_pages_viewed' => 'Не сте прегледали никакви страници',
'no_pages_recently_created' => 'Не са били създавани страници скоро',
'no_pages_recently_updated' => 'Не са били актуализирани страници скоро',
'permissions_intro' => 'Веднъж добавени, тези права ще вземат приоритет над всички други установени права.',
'permissions_enable' => 'Разреши уникални права',
'permissions_save' => 'Запази права',
- 'permissions_owner' => 'Owner',
+ 'permissions_owner' => 'Собственик',
// Search
'search_results' => 'Резултати от търсенето',
'search_no_pages' => 'Няма страници отговарящи на търсенето',
'search_for_term' => 'Търси :term',
'search_more' => 'Още резултати',
- 'search_advanced' => 'Advanced Search',
+ 'search_advanced' => 'Подробно търсене',
'search_terms' => 'Search Terms',
'search_content_type' => 'Тип на съдържание',
'search_exact_matches' => 'Точни съвпадения',
'search_permissions_set' => 'Задаване на права',
'search_created_by_me' => 'Създадено от мен',
'search_updated_by_me' => 'Обновено от мен',
- 'search_owned_by_me' => 'Owned by me',
+ 'search_owned_by_me' => 'Притежаван от мен',
'search_date_options' => 'Настройки на дати',
'search_updated_before' => 'Обновено преди',
'search_updated_after' => 'Обновено след',
'attachments_upload' => 'Прикачен файл',
'attachments_link' => 'Прикачване на линк',
'attachments_set_link' => 'Поставяне на линк',
- 'attachments_delete' => 'Are you sure you want to delete this attachment?',
+ 'attachments_delete' => 'Сигурни ли сте, че искате да изтриете прикачения файл?',
'attachments_dropzone' => 'Поставете файлове или цъкнете тук за да прикачите файл',
'attachments_no_files' => 'Няма прикачени фалове',
'attachments_explain_link' => 'Може да прикачите линк, ако не искате да качвате файл. Този линк може да бъде към друга страница или към файл в облакова пространство.',
'404_page_not_found' => 'Страницата не е намерена',
'sorry_page_not_found' => 'Страницата, която търсите не може да бъде намерена.',
'sorry_page_not_found_permission_warning' => 'Ако смятате, че тази страница съществува, най-вероятно нямате право да я преглеждате.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Назад към Начало',
'error_occurred' => 'Възникна грешка',
'app_down' => ':appName не е достъпно в момента',
'app_primary_color' => 'Основен цвят на приложението',
'app_primary_color_desc' => 'Изберете основния цвят на приложението, включително на банера, бутоните и линковете.',
'app_homepage' => 'Application Homepage',
- 'app_homepage_desc' => 'Select a view to show on the homepage instead of the default view. Page permissions are ignored for selected pages.',
- 'app_homepage_select' => 'Select a page',
- 'app_footer_links' => 'Footer Links',
- 'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
+ 'app_homepage_desc' => 'Изберете начална страница, която ще замени изгледа по подразбиране. Дефинираните права на страницата, която е избрана ще бъдат игнорирани.',
+ 'app_homepage_select' => 'Избери страница',
+ 'app_footer_links' => 'Футър линкове',
+ 'app_footer_links_desc' => 'Добави линк в съдържанието на футъра. Добавените линкове ще се показват долу в повечето страници, включително и в страниците, в които логването не е задължително. Можете да използвате заместител "trans::<key>", за да използвате дума дефинирана от системата. Пример: Използването на "trans::common.privacy_policy" ще покаже "Лични данни" или на "trans::common.terms_of_service" ще покаже "Общи условия".',
'app_footer_links_label' => 'Link Label',
- 'app_footer_links_url' => 'Link URL',
- 'app_footer_links_add' => 'Add Footer Link',
+ 'app_footer_links_url' => 'Линк URL',
+ 'app_footer_links_add' => 'Добави футър линк',
'app_disable_comments' => 'Disable Comments',
'app_disable_comments_toggle' => 'Disable comments',
'app_disable_comments_desc' => 'Disables comments across all pages in the application. <br> Existing comments are not shown.',
'maint_image_cleanup_nothing_found' => 'No unused images found, Nothing deleted!',
'maint_send_test_email' => 'Send a Test Email',
'maint_send_test_email_desc' => 'This sends a test email to your email address specified in your profile.',
- 'maint_send_test_email_run' => 'Send test email',
- 'maint_send_test_email_success' => 'Email sent to :address',
- 'maint_send_test_email_mail_subject' => 'Test Email',
- 'maint_send_test_email_mail_greeting' => 'Email delivery seems to work!',
- 'maint_send_test_email_mail_text' => 'Congratulations! As you received this email notification, your email settings seem to be configured properly.',
- 'maint_recycle_bin_desc' => 'Deleted shelves, books, chapters & pages are sent to the recycle bin so they can be restored or permanently deleted. Older items in the recycle bin may be automatically removed after a while depending on system configuration.',
- 'maint_recycle_bin_open' => 'Open Recycle Bin',
+ 'maint_send_test_email_run' => 'Изпрати тестов имейл',
+ 'maint_send_test_email_success' => 'Имейл изпратен на :address',
+ 'maint_send_test_email_mail_subject' => 'Тестов Имейл',
+ 'maint_send_test_email_mail_greeting' => 'Изпращането на Имейл работи!',
+ 'maint_send_test_email_mail_text' => 'Поздравления! След като получихте този имейл, Вашите имейл настройки са конфигурирани правилно.',
+ 'maint_recycle_bin_desc' => 'Изтрити рафти, книги, глави и страници се преместват в кошчето, откъдето можете да ги възстановите или изтриете завинаги. Стари съдържания в кошчето ще бъдат изтрити автоматично след време, в зависимост от настройките на системата.',
+ 'maint_recycle_bin_open' => 'Отвори Кошчето',
// Recycle Bin
- 'recycle_bin' => 'Recycle Bin',
+ 'recycle_bin' => 'Кошче',
'recycle_bin_desc' => 'Here you can restore items that have been deleted or choose to permanently remove them from the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
- 'recycle_bin_deleted_item' => 'Deleted Item',
- 'recycle_bin_deleted_by' => 'Deleted By',
- 'recycle_bin_deleted_at' => 'Deletion Time',
+ 'recycle_bin_deleted_item' => 'Изтрит предмет',
+ 'recycle_bin_deleted_by' => 'Изтрит от',
+ 'recycle_bin_deleted_at' => 'Час на изтриване',
'recycle_bin_permanently_delete' => 'Permanently Delete',
'recycle_bin_restore' => 'Restore',
'recycle_bin_contents_empty' => 'The recycle bin is currently empty',
'audit' => 'Audit Log',
'audit_desc' => 'This audit log displays a list of activities tracked in the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
'audit_event_filter' => 'Event Filter',
- 'audit_event_filter_no_filter' => 'No Filter',
- 'audit_deleted_item' => 'Deleted Item',
- 'audit_deleted_item_name' => 'Name: :name',
- 'audit_table_user' => 'User',
- 'audit_table_event' => 'Event',
+ 'audit_event_filter_no_filter' => 'Без филтър',
+ 'audit_deleted_item' => 'Изтрит предмет',
+ 'audit_deleted_item_name' => 'Име: :name',
+ 'audit_table_user' => 'Потребител',
+ 'audit_table_event' => 'Събитие',
'audit_table_related' => 'Related Item or Detail',
- 'audit_table_date' => 'Activity Date',
- 'audit_date_from' => 'Date Range From',
- 'audit_date_to' => 'Date Range To',
+ 'audit_table_date' => 'Дата на активност',
+ 'audit_date_from' => 'Време от',
+ 'audit_date_to' => 'Време до',
// Role Settings
- 'roles' => 'Roles',
- 'role_user_roles' => 'User Roles',
- 'role_create' => 'Create New Role',
- 'role_create_success' => 'Role successfully created',
- 'role_delete' => 'Delete Role',
- 'role_delete_confirm' => 'This will delete the role with the name \':roleName\'.',
- 'role_delete_users_assigned' => 'This role has :userCount users assigned to it. If you would like to migrate the users from this role select a new role below.',
- 'role_delete_no_migration' => "Don't migrate users",
- 'role_delete_sure' => 'Are you sure you want to delete this role?',
- 'role_delete_success' => 'Role successfully deleted',
+ 'roles' => 'Роли',
+ 'role_user_roles' => 'Потребителски роли',
+ 'role_create' => 'Създай нова роля',
+ 'role_create_success' => 'Ролята беше успешно създадена',
+ 'role_delete' => 'Изтрий роля',
+ 'role_delete_confirm' => 'Това ще изтрие ролята \':roleName\'.',
+ 'role_delete_users_assigned' => 'В тази роля се намират :userCount потребители. Ако искате да преместите тези потребители в друга роля, моля изберете нова роля отдолу.',
+ 'role_delete_no_migration' => "Не премествай потребителите в нова роля",
+ 'role_delete_sure' => 'Сигурни ли сте, че искате да изтриете тази роля?',
+ 'role_delete_success' => 'Ролята беше успешно изтрита',
'role_edit' => 'Редактиране на роля',
'role_details' => 'Детайли на роля',
'role_name' => 'Име на ролята',
'role_access_api' => 'Достъп до API на системата',
'role_manage_settings' => 'Управление на настройките на приложението',
'role_asset' => 'Настройки за достъп до активи',
- 'roles_system_warning' => 'Be aware that access to any of the above three permissions can allow a user to alter their own privileges or the privileges of others in the system. Only assign roles with these permissions to trusted users.',
- 'role_asset_desc' => 'Тези настойки за достъп контролират достъпа по подразбиране до активите в системата. Настойките за достъп до книги, глави и страници ще отменят тези настройки.',
+ 'roles_system_warning' => 'Важно: Добавянето на потребител в някое от горните три роли може да му позволи да промени собствените си права или правата на другите в системата. Възлагайте тези роли само на доверени потребители.',
+ 'role_asset_desc' => 'Тези настройки за достъп контролират достъпа по подразбиране до активите в системата. Настройките за достъп до книги, глави и страници ще отменят тези настройки.',
'role_asset_admins' => 'Администраторите автоматично получават достъп до цялото съдържание, но тези опции могат да показват или скриват опциите за потребителския интерфейс.',
'role_all' => 'Всички',
'role_own' => 'Собствени',
'role_controlled_by_asset' => 'Controlled by the asset they are uploaded to',
- 'role_save' => 'Save Role',
- 'role_update_success' => 'Role successfully updated',
- 'role_users' => 'Users in this role',
- 'role_users_none' => 'No users are currently assigned to this role',
+ 'role_save' => 'Запази ролята',
+ 'role_update_success' => 'Ролята беше успешно актуализирана',
+ 'role_users' => 'Потребители в тази роля',
+ 'role_users_none' => 'В момента няма потребители, назначени за тази роля',
// Users
- 'users' => 'Users',
- 'user_profile' => 'User Profile',
- 'users_add_new' => 'Add New User',
- 'users_search' => 'Search Users',
- 'users_latest_activity' => 'Latest Activity',
- 'users_details' => 'User Details',
+ 'users' => 'Потребители',
+ 'user_profile' => 'Потребителски профил',
+ 'users_add_new' => 'Добави нов потребител',
+ 'users_search' => 'Търси Потребители',
+ 'users_latest_activity' => 'Последна активност',
+ 'users_details' => 'Потребителски детайли',
'users_details_desc' => 'Set a display name and an email address for this user. The email address will be used for logging into the application.',
'users_details_desc_no_email' => 'Set a display name for this user so others can recognise them.',
'users_role' => 'User Roles',
'users_external_auth_id_desc' => 'This is the ID used to match this user when communicating with your external authentication system.',
'users_password_warning' => 'Only fill the below if you would like to change your password.',
'users_system_public' => 'This user represents any guest users that visit your instance. It cannot be used to log in but is assigned automatically.',
- 'users_delete' => 'Delete User',
- 'users_delete_named' => 'Delete user :userName',
- 'users_delete_warning' => 'This will fully delete this user with the name \':userName\' from the system.',
- 'users_delete_confirm' => 'Are you sure you want to delete this user?',
- 'users_migrate_ownership' => 'Migrate Ownership',
+ 'users_delete' => 'Изтрий потребител',
+ 'users_delete_named' => 'Изтрий потребителя :userName',
+ 'users_delete_warning' => 'Това изцяло ще изтрие този потребител с името \':userName\' от системата.',
+ 'users_delete_confirm' => 'Сигурни ли сте, че искате да изтриете този потребител?',
+ 'users_migrate_ownership' => 'Мигрирайте собствеността на сайта',
'users_migrate_ownership_desc' => 'Select a user here if you want another user to become the owner of all items currently owned by this user.',
- 'users_none_selected' => 'No user selected',
+ 'users_none_selected' => 'Няма избрани потребители',
'users_delete_success' => 'User successfully removed',
'users_edit' => 'Edit User',
'users_edit_profile' => 'Edit Profile',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
return [
// Standard laravel validation lines
- 'accepted' => 'The :attribute must be accepted.',
- 'active_url' => 'The :attribute is not a valid URL.',
- 'after' => 'The :attribute must be a date after :date.',
- 'alpha' => 'The :attribute may only contain letters.',
- 'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.',
- 'alpha_num' => 'The :attribute may only contain letters and numbers.',
- 'array' => 'The :attribute must be an array.',
- 'before' => 'The :attribute must be a date before :date.',
+ 'accepted' => ':attribute трябва да бъде одобрен.',
+ 'active_url' => ':attribute не е валиден URL адрес.',
+ 'after' => ':attribute трябва да е дата след :date.',
+ 'alpha' => ':attribute може да съдържа само букви.',
+ 'alpha_dash' => ':attribute може да съдържа само букви, числа, тире и долна черта.',
+ 'alpha_num' => ':attribute може да съдържа само букви и числа.',
+ 'array' => ':attribute трябва да е масив (array).',
+ 'before' => ':attribute трябва да е дата след :date.',
'between' => [
- 'numeric' => 'The :attribute must be between :min and :max.',
- 'file' => 'The :attribute must be between :min and :max kilobytes.',
- 'string' => 'The :attribute must be between :min and :max characters.',
+ 'numeric' => ':attribute трябва да е между :min и :max.',
+ 'file' => ':attribute трябва да е между :min и :max килобайта.',
+ 'string' => 'Дължината на :attribute трябва да бъде между :min и :max символа.',
'array' => 'The :attribute must have between :min and :max items.',
],
- 'boolean' => 'The :attribute field must be true or false.',
- 'confirmed' => 'The :attribute confirmation does not match.',
- 'date' => 'The :attribute is not a valid date.',
- 'date_format' => 'The :attribute does not match the format :format.',
- 'different' => 'The :attribute and :other must be different.',
- 'digits' => 'The :attribute must be :digits digits.',
- 'digits_between' => 'The :attribute must be between :min and :max digits.',
- 'email' => 'The :attribute must be a valid email address.',
- 'ends_with' => 'The :attribute must end with one of the following: :values',
- 'filled' => 'The :attribute field is required.',
+ 'boolean' => 'Полето :attribute трябва да съдържа булева стойност (true или false).',
+ 'confirmed' => 'Потвърждението на :attribute не съвпада.',
+ 'date' => ':attribute не е валидна дата.',
+ 'date_format' => ':attribute не е в посоченият формат - :format.',
+ 'different' => ':attribute и :other трябва да са различни.',
+ 'digits' => ':attribute трябва да съдържа :digits цифри.',
+ 'digits_between' => ':attribute трябва да бъде с дължина между :min и :max цифри.',
+ 'email' => ':attribute трябва да бъде валиден имейл адрес.',
+ 'ends_with' => ':attribute трябва да свършва с един от следните символи: :values',
+ 'filled' => 'Полето :attribute е задължителен.',
'gt' => [
- 'numeric' => 'The :attribute must be greater than :value.',
- 'file' => 'The :attribute must be greater than :value kilobytes.',
- 'string' => 'The :attribute must be greater than :value characters.',
+ 'numeric' => ':attribute трябва да бъде по-голям от :value.',
+ 'file' => 'Големината на :attribute трябва да бъде по-голямо от :value килобайта.',
+ 'string' => 'Дължината на :attribute трябва да бъде по-голямо от :value символа.',
'array' => 'The :attribute must have more than :value items.',
],
'gte' => [
'numeric' => 'The :attribute must be greater than or equal :value.',
- 'file' => 'The :attribute must be greater than or equal :value kilobytes.',
- 'string' => 'The :attribute must be greater than or equal :value characters.',
+ 'file' => 'Големината на :attribute трябва да бъде по-голямо или равно на :value килобайта.',
+ 'string' => 'Дължината на :attribute трябва да бъде по-голямо или равно на :value символа.',
'array' => 'The :attribute must have :value items or more.',
],
- 'exists' => 'The selected :attribute is invalid.',
- 'image' => 'The :attribute must be an image.',
- 'image_extension' => 'The :attribute must have a valid & supported image extension.',
- 'in' => 'The selected :attribute is invalid.',
- 'integer' => 'The :attribute must be an integer.',
- 'ip' => 'The :attribute must be a valid IP address.',
- 'ipv4' => 'The :attribute must be a valid IPv4 address.',
- 'ipv6' => 'The :attribute must be a valid IPv6 address.',
- 'json' => 'The :attribute must be a valid JSON string.',
+ 'exists' => 'Избраният :attribute е невалиден.',
+ 'image' => ':attribute трябва да e изображение.',
+ 'image_extension' => ':attribute трябва да е валиден и/или допустим графичен файлов формат.',
+ 'in' => 'Избраният :attribute е невалиден.',
+ 'integer' => ':attribute трябва да бъде цяло число.',
+ 'ip' => ':attribute трябва да бъде валиден IP адрес.',
+ 'ipv4' => ':attribute трябва да бъде валиден IPv4 адрес.',
+ 'ipv6' => ':attribute трябва да бъде валиден IPv6 адрес.',
+ 'json' => ':attribute трябва да съдържа валиден JSON.',
'lt' => [
- 'numeric' => 'The :attribute must be less than :value.',
- 'file' => 'The :attribute must be less than :value kilobytes.',
- 'string' => 'The :attribute must be less than :value characters.',
+ 'numeric' => ':attribute трябва да бъде по-малко от :value.',
+ 'file' => 'Големината на :attribute трябва да бъде по-малко от :value килобайта.',
+ 'string' => 'Дължината на :attribute трябва да бъде по-малко от :value символа.',
'array' => 'The :attribute must have less than :value items.',
],
'lte' => [
- 'numeric' => 'The :attribute must be less than or equal :value.',
- 'file' => 'The :attribute must be less than or equal :value kilobytes.',
- 'string' => 'The :attribute must be less than or equal :value characters.',
+ 'numeric' => ':attribute трябва да бъде по-малко или равно на :value.',
+ 'file' => 'Големината на :attribute трябва да бъде по-малко или равно на :value килобайта.',
+ 'string' => 'Дължината на :attribute трябва да бъде по-малко или равно на :value символа.',
'array' => 'The :attribute must not have more than :value items.',
],
'max' => [
- 'numeric' => 'The :attribute may not be greater than :max.',
- 'file' => 'The :attribute may not be greater than :max kilobytes.',
- 'string' => 'The :attribute may not be greater than :max characters.',
+ 'numeric' => ':attribute не трябва да бъде по-голям от :max.',
+ 'file' => 'Големината на :attribute не може да бъде по-голямо от :value килобайта.',
+ 'string' => 'Дължината на :attribute не може да бъде по-голямо от :value символа.',
'array' => 'The :attribute may not have more than :max items.',
],
'mimes' => 'The :attribute must be a file of type: :values.',
'bookshelf_delete' => 'je izbrisao/la policu za knjige',
'bookshelf_delete_notification' => 'Polica za knjige Uspješno Izbrisana',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'je komentarisao/la na',
'permissions_update' => 'je ažurirao/la dozvole',
'remove' => 'Ukloni',
'add' => 'Dodaj',
'fullscreen' => 'Prikaz preko čitavog ekrana',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Opcije sortiranja',
'breadcrumb' => 'Navigacijske stavke',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Meni profila',
'view_profile' => 'Pogledaj profil',
'edit_profile' => 'Izmjeni profil',
// Layout tabs
'tab_info' => 'Informacije',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Sadržaj',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Ukoliko imate poteškoća sa pritiskom na ":actionText" dugme, kopirajte i zaljepite URL koji se nalazi ispod u vaš web pretraživač:',
'images' => 'Slike',
'my_recent_drafts' => 'Moje nedavne skice',
'my_recently_viewed' => 'Moji nedavni pregledi',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Niste pogledali nijednu stranicu',
'no_pages_recently_created' => 'Nijedna stranica nije napravljena nedavno',
'no_pages_recently_updated' => 'Niijedna stranica nije ažurirana nedavno',
'404_page_not_found' => 'Stranica nije pronađena',
'sorry_page_not_found' => 'Stranica koju ste tražili nije pronađena.',
'sorry_page_not_found_permission_warning' => 'Ako ste očekivali da ova stranica postoji, možda nemate privilegije da joj pristupite.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Nazad na početnu stranu',
'error_occurred' => 'Desila se greška',
'app_down' => ':appName trenutno nije u funkciji',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'ha suprimit un prestatge',
'bookshelf_delete_notification' => 'Prestatge suprimit correctament',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'ha comentat a',
'permissions_update' => 'ha actualitzat els permisos',
*/
return [
- 'failed' => 'Les credencials no coincideixen amb les que tenim emmagatzemades.',
- 'throttle' => 'Massa intents d\'iniciar la sessió. Torneu-ho a provar d\'aquí a :seconds segons.',
+ 'failed' => 'Les credencials no coincideixen amb les que hi ha emmagatzemades.',
+ 'throttle' => 'Massa intents d\'inici de sessió. Torna-ho a provar d\'aquí a :seconds segons.',
// Login & Register
'sign_up' => 'Registra-m\'hi',
'create_account' => 'Crea el compte',
'already_have_account' => 'Ja teniu un compte?',
'dont_have_account' => 'No teniu cap compte?',
- 'social_login' => 'Inici de sessió social',
+ 'social_login' => 'Inici de sessió amb xarxes social',
'social_registration' => 'Registre social',
'social_registration_text' => 'Registreu-vos i inicieu la sessió fent servir un altre servei.',
// Buttons
'cancel' => 'Cancel·la',
'confirm' => 'D\'acord',
- 'back' => 'Endarrere',
+ 'back' => 'Enrere',
'save' => 'Desa',
'continue' => 'Continua',
'select' => 'Selecciona',
'remove' => 'Elimina',
'add' => 'Afegeix',
'fullscreen' => 'Pantalla completa',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Opcions d\'ordenació',
'sort_ascending' => 'Ordre ascendent',
'sort_descending' => 'Ordre descendent',
'sort_name' => 'Nom',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Per defecte',
'sort_created_at' => 'Data de creació',
'sort_updated_at' => 'Data d\'actualització',
'breadcrumb' => 'Ruta de navegació',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Menú del perfil',
'view_profile' => 'Mostra el perfil',
'edit_profile' => 'Edita el perfil',
// Layout tabs
'tab_info' => 'Informació',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Contingut',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Si teniu problemes per fer clic al botó ":actionText", copieu i enganxeu l\'URL següent al vostre navegador web:',
'images' => 'Imatges',
'my_recent_drafts' => 'Els vostres esborranys recents',
'my_recently_viewed' => 'Les vostres visualitzacions recents',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'No heu vist cap pàgina',
'no_pages_recently_created' => 'No s\'ha creat cap pàgina fa poc',
'no_pages_recently_updated' => 'No s\'ha actualitzat cap pàgina fa poc',
'404_page_not_found' => 'No s\'ha trobat la pàgina',
'sorry_page_not_found' => 'No hem pogut trobar la pàgina que cerqueu.',
'sorry_page_not_found_permission_warning' => 'Si esperàveu que existís, és possible que no tingueu permisos per a veure-la.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Torna a l\'inici',
'error_occurred' => 'S\'ha produït un error',
'app_down' => ':appName està fora de servei en aquests moments',
return [
'password' => 'Les contrasenyes han de tenir com a mínim vuit caràcters i la confirmació ha de coincidir.',
- 'user' => "No s'ha trobat cap usuari amb aquesta adreça electrònica.",
- 'token' => 'El testimoni de reinicialització de la contrasenya no és vàlid per a aquesta adreça electrònica.',
- 'sent' => 'Us hem enviat un enllaç per a restablir la contrasenya!',
- 'reset' => 'S\'ha restablert la vostra contrasenya!',
+ 'user' => "No s'ha trobat cap usuari amb aquest correu electrònic.",
+ 'token' => 'El token de restabliment de contrasenya no és vàlid per aquest correu electrònic.',
+ 'sent' => 'T\'hem enviat un enllaç per a restablir la contrasenya!',
+ 'reset' => 'S\'ha restablert la teva contrasenya!',
];
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
return [
// Standard laravel validation lines
- 'accepted' => 'Cal que accepteu el camp :attribute.',
- 'active_url' => 'El camp :attribute no és un URL vàlid.',
+ 'accepted' => 'Cal que acceptis :attribute.',
+ 'active_url' => 'L\':attribute no és un URL vàlid.',
'after' => 'El camp :attribute ha de ser una data posterior a :date.',
'alpha' => 'El camp :attribute només pot contenir lletres.',
'alpha_dash' => 'El camp :attribute només pot contenir lletres, números, guions i guions baixos.',
'bookshelf_delete' => 'odstranil/a knihovnu',
'bookshelf_delete_notification' => 'Knihovna byla úspěšně odstraněna',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'okomentoval/a',
'permissions_update' => 'updated permissions',
'remove' => 'Odebrat',
'add' => 'Přidat',
'fullscreen' => 'Celá obrazovka',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Možnosti řazení',
'breadcrumb' => 'Drobečková navigace',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Nabídka profilu',
'view_profile' => 'Zobrazit profil',
'edit_profile' => 'Upravit profil',
// Layout tabs
'tab_info' => 'Informace',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Obsah',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Pokud se vám nedaří kliknout na tlačítko „:actionText“, zkopírujte a vložte níže uvedenou URL do vašeho webového prohlížeče:',
'images' => 'Obrázky',
'my_recent_drafts' => 'Mé nedávné koncepty',
'my_recently_viewed' => 'Mé nedávno zobrazené',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Nezobrazili jste žádné stránky',
'no_pages_recently_created' => 'Nedávno nebyly vytvořeny žádné stránky',
'no_pages_recently_updated' => 'Nedávno nebyly aktualizovány žádné stránky',
'404_page_not_found' => 'Stránka nenalezena',
'sorry_page_not_found' => 'Omlouváme se, ale stránka, kterou hledáte nebyla nalezena.',
'sorry_page_not_found_permission_warning' => 'Pokud očekáváte, že by stránka měla existovat, možná jen nemáte oprávnění pro její zobrazení.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Návrat domů',
'error_occurred' => 'Nastala chyba',
'app_down' => ':appName je momentálně vypnutá',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'chapter_create' => 'oprettede kapitel',
'chapter_create_notification' => 'Kapitel blev oprettet',
'chapter_update' => 'opdaterede kapitel',
- 'chapter_update_notification' => 'Kapitel blev opdateret',
+ 'chapter_update_notification' => 'Kapitlet blev opdateret',
'chapter_delete' => 'slettede kapitel',
'chapter_delete_notification' => 'Kapitel blev slettet',
'chapter_move' => 'flyttede kapitel',
'bookshelf_delete' => 'slettede bogreol',
'bookshelf_delete_notification' => 'Bogreolen blev opdateret',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'kommenterede til',
- 'permissions_update' => 'updated permissions',
+ 'permissions_update' => 'Tilladelser opdateret',
];
*/
return [
- 'failed' => 'Det indtastede stemmer ikke overens med vores registrering.',
- 'throttle' => 'For mange mislykkede loginforsøg. Prøv igen om :seconds seconds.',
+ 'failed' => 'Dee indtastede brugeroplysninger stemmer ikke overens med vores registreringer.',
+ 'throttle' => 'For mange mislykkede loginforsøg. Prøv igen om :seconds sekunder.',
// Login & Register
'sign_up' => 'Registrér',
'email' => 'E-mail',
'password' => 'Adgangskode',
'password_confirm' => 'Bekræft adgangskode',
- 'password_hint' => 'Skal være på mindst 8 karakterer',
+ 'password_hint' => 'Skal være på mindst 7 karakterer',
'forgot_password' => 'Glemt Adgangskode?',
- 'remember_me' => 'Husk Mig',
+ 'remember_me' => 'Husk mig',
'ldap_email_hint' => 'Angiv venligst din kontos e-mail.',
- 'create_account' => 'Opret Konto',
+ 'create_account' => 'Opret konto',
'already_have_account' => 'Har du allerede en konto?',
'dont_have_account' => 'Har du ikke en konto?',
'social_login' => 'Social Log ind',
'copy' => 'Kopier',
'reply' => 'Besvar',
'delete' => 'Slet',
- 'delete_confirm' => 'Confirm Deletion',
+ 'delete_confirm' => 'Bekræft sletning',
'search' => 'Søg',
'search_clear' => 'Ryd søgning',
'reset' => 'Nulstil',
'remove' => 'Fjern',
'add' => 'Tilføj',
'fullscreen' => 'Fuld skærm',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Sorteringsindstillinger',
'sort_ascending' => 'Sorter stigende',
'sort_descending' => 'Sorter faldende',
'sort_name' => 'Navn',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Standard',
'sort_created_at' => 'Oprettelsesdato',
'sort_updated_at' => 'Opdateringsdato',
'breadcrumb' => 'Brødkrumme',
// Header
+ 'header_menu_expand' => 'Udvid header menu',
'profile_menu' => 'Profilmenu',
'view_profile' => 'Vis profil',
'edit_profile' => 'Redigér Profil',
// Layout tabs
'tab_info' => 'Info',
+ 'tab_info_label' => 'Faneblad: Vis sekundær information',
'tab_content' => 'Indhold',
+ 'tab_content_label' => 'Faneblad: Vis primær indhold',
// Email Content
'email_action_help' => 'Hvis du har problemer med at trykke på ":actionText" knappen, prøv at kopiere og indsætte linket herunder ind i din webbrowser:',
// Footer Link Options
// Not directly used but available for convenience to users.
- 'privacy_policy' => 'Privacy Policy',
- 'terms_of_service' => 'Terms of Service',
+ 'privacy_policy' => 'Privatlivspolitik',
+ 'terms_of_service' => 'Tjenestevilkår',
];
'image_load_more' => 'Indlæse mere',
'image_image_name' => 'Billednavn',
'image_delete_used' => 'Dette billede er brugt på siderne nedenfor.',
- 'image_delete_confirm_text' => 'Are you sure you want to delete this image?',
+ 'image_delete_confirm_text' => 'Er du sikker på at du vil slette dette billede?',
'image_select_image' => 'Vælg billede',
'image_dropzone' => 'Træk-og-slip billede eller klik her for at uploade',
'images_deleted' => 'Billede slettet',
'code_editor' => 'Rediger kode',
'code_language' => 'Kodesprog',
'code_content' => 'Kodeindhold',
- 'code_session_history' => 'Session History',
+ 'code_session_history' => 'Sessionshistorik',
'code_save' => 'Gem kode',
];
'meta_created_name' => 'Oprettet :timeLength af :user',
'meta_updated' => 'Opdateret :timeLength',
'meta_updated_name' => 'Opdateret :timeLength af :user',
- 'meta_owned_name' => 'Owned by :user',
+ 'meta_owned_name' => 'Ejet af :user',
'entity_select' => 'Vælg emne',
'images' => 'Billeder',
'my_recent_drafts' => 'Mine seneste kladder',
'my_recently_viewed' => 'Mine senest viste',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Du har ikke besøgt nogle sider',
'no_pages_recently_created' => 'Ingen sider er blevet oprettet for nyligt',
'no_pages_recently_updated' => 'Ingen sider er blevet opdateret for nyligt',
'permissions_intro' => 'Når de er aktiveret, vil disse tilladelser have prioritet over alle indstillede rolletilladelser.',
'permissions_enable' => 'Aktivér tilpassede tilladelser',
'permissions_save' => 'Gem tilladelser',
- 'permissions_owner' => 'Owner',
+ 'permissions_owner' => 'Ejer',
// Search
'search_results' => 'Søgeresultater',
'search_no_pages' => 'Ingen sider matchede søgning',
'search_for_term' => 'Søgning for :term',
'search_more' => 'Flere resultater',
- 'search_advanced' => 'Advanced Search',
- 'search_terms' => 'Search Terms',
+ 'search_advanced' => 'Avanceret søgning',
+ 'search_terms' => 'Søgeord',
'search_content_type' => 'Indholdstype',
'search_exact_matches' => 'Nøjagtige matches',
'search_tags' => 'Tagsøgninger',
'search_permissions_set' => 'Rettigheders sæt',
'search_created_by_me' => 'Oprettet af mig',
'search_updated_by_me' => 'Opdateret af mig',
- 'search_owned_by_me' => 'Owned by me',
+ 'search_owned_by_me' => 'Ejet af mig',
'search_date_options' => 'Datoindstillinger',
'search_updated_before' => 'Opdateret før',
'search_updated_after' => 'Opdateret efter',
'chapters_create' => 'Opret nyt kapitel',
'chapters_delete' => 'Slet kapitel',
'chapters_delete_named' => 'Slet kapitel :chapterName',
- 'chapters_delete_explain' => 'This will delete the chapter with the name \':chapterName\'. All pages that exist within this chapter will also be deleted.',
+ 'chapters_delete_explain' => 'Dette vil slette kapitlet med navnet \':chapterName\'. Alle sider i dette kapitel vil også blive slettet.',
'chapters_delete_confirm' => 'Er du sikker på du vil slette dette kapitel?',
'chapters_edit' => 'Rediger kapitel',
'chapters_edit_named' => 'Rediger kapitel :chapterName',
'pages_revisions' => 'Sidserevisioner',
'pages_revisions_named' => 'Siderevisioner for :pageName',
'pages_revision_named' => 'Siderevision for :pageName',
- 'pages_revision_restored_from' => 'Restored from #:id; :summary',
+ 'pages_revision_restored_from' => 'Genoprettet fra #:id; :summary',
'pages_revisions_created_by' => 'Oprettet af',
'pages_revisions_date' => 'Revisionsdato',
'pages_revisions_number' => '#',
'attachments_upload' => 'Upload fil',
'attachments_link' => 'Vedhæft link',
'attachments_set_link' => 'Sæt link',
- 'attachments_delete' => 'Are you sure you want to delete this attachment?',
+ 'attachments_delete' => 'Er du sikker på at du vil slette denne vedhæftning?',
'attachments_dropzone' => 'Slip filer eller klik her for at vedhæfte en fil',
'attachments_no_files' => 'Ingen filer er blevet overført',
'attachments_explain_link' => 'Du kan vedhæfte et link, hvis du foretrækker ikke at uploade en fil. Dette kan være et link til en anden side eller et link til en fil i skyen.',
'attachments_link_url' => 'Link til filen',
'attachments_link_url_hint' => 'Adresse (URL) på side eller fil',
'attach' => 'Vedhæft',
- 'attachments_insert_link' => 'Add Attachment Link to Page',
+ 'attachments_insert_link' => 'Tilføj vedhæftningslink til side',
'attachments_edit_file' => 'Rediger fil',
'attachments_edit_file_name' => 'Filnavn',
'attachments_edit_drop_upload' => 'Slip filer eller klik her for at uploade og overskrive',
'404_page_not_found' => 'Siden blev ikke fundet',
'sorry_page_not_found' => 'Beklager, siden du leder efter blev ikke fundet.',
'sorry_page_not_found_permission_warning' => 'Hvis du forventede, at denne side skulle eksistere, har du muligvis ikke tilladelse til at se den.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Gå tilbage til hjem',
'error_occurred' => 'Der opstod en fejl',
'app_down' => ':appName er nede lige nu',
// Common Messages
'settings' => 'Indstillinger',
'settings_save' => 'Gem indstillinger',
- 'settings_save_success' => 'Indstillinger gemt',
+ 'settings_save_success' => 'Indstillingerne blev gemt',
// App Settings
'app_customization' => 'Tilpasning',
- 'app_features_security' => 'Funktioner & sikkerhed',
- 'app_name' => 'Programnavn',
- 'app_name_desc' => 'Dette er navnet vist i headeren og i systemafsendte E-Mails.',
+ 'app_features_security' => 'Funktionalitet og sikkerhed',
+ 'app_name' => 'Applikationsnavn',
+ 'app_name_desc' => 'Dette navn vises i headeren og i alle e-mails sendt fra systemet.',
'app_name_header' => 'Vis navn i header',
'app_public_access' => 'Offentlig adgang',
'app_public_access_desc' => 'Aktivering af denne funktion giver besøgende, der ikke er logget ind, adgang til indhold i din BookStack-instans.',
'app_public_viewing' => 'Tillad offentlig visning?',
'app_secure_images' => 'Højere sikkerhed for billeduploads',
'app_secure_images_toggle' => 'Aktiver højere sikkerhed for billeduploads',
- 'app_secure_images_desc' => 'Af ydeevneårsager er alle billeder offentlige. Denne funktion tilføjer en tilfældig, vanskelig at gætte streng foran billed-Url\'er. Sørg for, at mappeindekser ikke er aktiveret for at forhindre nem adgang.',
+ 'app_secure_images_desc' => 'Af performanceårsager er alle billeder offentlige. Denne funktion tilføjer en tilfældig, vanskelig at gætte streng foran billed-url\'er. Sørg for, at mappeindeksering ikke er aktiveret for at forhindre nem adgang.',
'app_editor' => 'Sideeditor',
'app_editor_desc' => 'Vælg hvilken editor der skal bruges af alle brugere til at redigere sider.',
- 'app_custom_html' => 'Tilpasset HTML head-indhold',
- 'app_custom_html_desc' => 'Al indhold tilføjet her, vil blive indsat i bunden af <head> sektionen på alle sider. Dette er brugbart til overskrivning af styling og tilføjelse af analysekode.',
- 'app_custom_html_disabled_notice' => 'Brugerdefineret HTML-head indhold er deaktiveret på denne indstillingsside for at sikre, at ødelæggende ændringer kan rettes.',
- 'app_logo' => 'Programlogo',
- 'app_logo_desc' => 'Dette billede skal være 43px højt. <br> Større billeder vil blive skaleret ned.',
- 'app_primary_color' => 'Primær programfarve',
+ 'app_custom_html' => 'Tilpasset HTML head indhold',
+ 'app_custom_html_desc' => 'Alt indhold tilføjet her, vil blive indsat i bunden af <head> sektionen på alle sider. Dette er brugbart til overskrivning af styles og tilføjelse af analytics kode.',
+ 'app_custom_html_disabled_notice' => 'Brugerdefineret HTML head indhold er deaktiveret på denne indstillingsside for at, at ændringer kan rulles tilbage.',
+ 'app_logo' => 'Applikationslogo',
+ 'app_logo_desc' => 'Dette billede skal være 43px højt. <br>Store billeder vil blive skaleret ned.',
+ 'app_primary_color' => 'Primær applikationsfarve',
'app_primary_color_desc' => 'Sætter den primære farve for applikationen herunder banneret, knapper og links.',
- 'app_homepage' => 'Programforside',
- 'app_homepage_desc' => 'Vælg en visning, der skal vises på startsiden i stedet for standardvisningen. Sidetilladelser ignoreres for valgte sider.',
+ 'app_homepage' => 'Applikationsforside',
+ 'app_homepage_desc' => 'Vælg en visning, der skal vises på forsiden i stedet for standardvisningen. Sidetilladelser ignoreres for de valgte sider.',
'app_homepage_select' => 'Vælg en side',
- 'app_footer_links' => 'Footer Links',
- 'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
- 'app_footer_links_label' => 'Link Label',
+ 'app_footer_links' => 'Footer links',
+ 'app_footer_links_desc' => 'Tilføj links til footeren. Linksene vil blive vist nederst på de fleste sider, inkluderet sider, som ikke kræver login. Brug en label med "trans::<key>" for at bruge systemdefinerede oversættelser. For eksempel: "trans::common.privacy_policy" giver den oversatte tekst "Privacy Policy" og "trans::common.terms_of_service" vil give den oversatte tekst "Terms of Service".',
+ 'app_footer_links_label' => 'Link label',
'app_footer_links_url' => 'Link URL',
- 'app_footer_links_add' => 'Add Footer Link',
+ 'app_footer_links_add' => 'Tilføj footer link',
'app_disable_comments' => 'Deaktiver kommentarer',
'app_disable_comments_toggle' => 'Deaktiver kommentar',
'app_disable_comments_desc' => 'Deaktiverer kommentarer på tværs af alle sider i applikationen. <br> Eksisterende kommentarer vises ikke.',
'maint' => 'Vedligeholdelse',
'maint_image_cleanup' => 'Ryd op i billeder',
'maint_image_cleanup_desc' => "Scanner side & revisionsindhold for at kontrollere, hvilke billeder og tegninger, der i øjeblikket er i brug, og hvilke billeder, der er overflødige. Sørg for, at du opretter en komplet database og billedbackup, før du kører dette.",
- 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
+ 'maint_delete_images_only_in_revisions' => 'Slet også billeder, der kun findes i gamle siderevisioner',
'maint_image_cleanup_run' => 'Kør Oprydning',
'maint_image_cleanup_warning' => 'der blev fundet :count potentielt ubrugte billeder. Er du sikker på, at du vil slette disse billeder?',
'maint_image_cleanup_success' => ':count: potentielt ubrugte billeder fundet og slettet!',
'maint_send_test_email_mail_subject' => 'Test E-Mail',
'maint_send_test_email_mail_greeting' => 'E-Mail levering ser ud til at virke!',
'maint_send_test_email_mail_text' => 'Tillykke! Da du har modtaget denne mailnotifikation, ser det ud som om, at dine mailindstillinger er opsat korrekt.',
- 'maint_recycle_bin_desc' => 'Deleted shelves, books, chapters & pages are sent to the recycle bin so they can be restored or permanently deleted. Older items in the recycle bin may be automatically removed after a while depending on system configuration.',
- 'maint_recycle_bin_open' => 'Open Recycle Bin',
+ 'maint_recycle_bin_desc' => 'Slettede hylder, bøger, kapitler og sider overføres til papirkurven, så de kan gendannes eller slettes permanent. Ældre elementer i papirkurven fjernes automatisk efter et stykke tid afhængigt af systemets konfiguration.',
+ 'maint_recycle_bin_open' => 'Åbn papirkurven',
// Recycle Bin
- 'recycle_bin' => 'Recycle Bin',
- 'recycle_bin_desc' => 'Here you can restore items that have been deleted or choose to permanently remove them from the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
- 'recycle_bin_deleted_item' => 'Deleted Item',
- 'recycle_bin_deleted_by' => 'Deleted By',
- 'recycle_bin_deleted_at' => 'Deletion Time',
- 'recycle_bin_permanently_delete' => 'Permanently Delete',
- 'recycle_bin_restore' => 'Restore',
- 'recycle_bin_contents_empty' => 'The recycle bin is currently empty',
- 'recycle_bin_empty' => 'Empty Recycle Bin',
- 'recycle_bin_empty_confirm' => 'This will permanently destroy all items in the recycle bin including content contained within each item. Are you sure you want to empty the recycle bin?',
- 'recycle_bin_destroy_confirm' => 'This action will permanently delete this item, along with any child elements listed below, from the system and you will not be able to restore this content. Are you sure you want to permanently delete this item?',
- 'recycle_bin_destroy_list' => 'Items to be Destroyed',
- 'recycle_bin_restore_list' => 'Items to be Restored',
- 'recycle_bin_restore_confirm' => 'This action will restore the deleted item, including any child elements, to their original location. If the original location has since been deleted, and is now in the recycle bin, the parent item will also need to be restored.',
- 'recycle_bin_restore_deleted_parent' => 'The parent of this item has also been deleted. These will remain deleted until that parent is also restored.',
- 'recycle_bin_destroy_notification' => 'Deleted :count total items from the recycle bin.',
- 'recycle_bin_restore_notification' => 'Restored :count total items from the recycle bin.',
+ 'recycle_bin' => 'Papirkurv',
+ 'recycle_bin_desc' => 'Her kan du gendanne elementer, der er blevet slettet eller vælge at permanent fjerne dem fra systemet. Denne liste er ufiltreret, i modsætning til lignende aktivitetslister i systemet, hvor tilladelsesfiltre anvendes.',
+ 'recycle_bin_deleted_item' => 'Slettet element',
+ 'recycle_bin_deleted_by' => 'Slettet af',
+ 'recycle_bin_deleted_at' => 'Sletningstidspunkt',
+ 'recycle_bin_permanently_delete' => 'Slet permanent',
+ 'recycle_bin_restore' => 'Gendan',
+ 'recycle_bin_contents_empty' => 'Papirkurven er tom',
+ 'recycle_bin_empty' => 'Tøm papirkurv',
+ 'recycle_bin_empty_confirm' => 'Dette vil permanent slette alle elementer i papirkurven, inkluderet hvert elements indhold. Er du sikker på, at du vil tømme papirkurven?',
+ 'recycle_bin_destroy_confirm' => 'Denne handling sletter dette element permanent, sammen med elementerne anført nedenfor, fra systemet. Du vil ikke være i stand til at gendanne dette indhold. Er du sikker på, at du vil slette dette element permanent?',
+ 'recycle_bin_destroy_list' => 'Elementer der skal slettes',
+ 'recycle_bin_restore_list' => 'Elementer der skal gendannes',
+ 'recycle_bin_restore_confirm' => 'Denne handling vil gendanne det slettede element, herunder alle underelementer, til deres oprindelige placering. Hvis den oprindelige placering siden er blevet slettet, og nu er i papirkurven, vil det overordnede element også skulle gendannes.',
+ 'recycle_bin_restore_deleted_parent' => 'Det overordnede element til dette element er også blevet slettet. Disse vil forblive slettet indtil det overordnede også er gendannet.',
+ 'recycle_bin_destroy_notification' => 'Slettede :count elementer fra papirkurven.',
+ 'recycle_bin_restore_notification' => 'Gendannede :count elementer fra papirkurven.',
// Audit Log
- 'audit' => 'Audit Log',
- 'audit_desc' => 'This audit log displays a list of activities tracked in the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
- 'audit_event_filter' => 'Event Filter',
- 'audit_event_filter_no_filter' => 'No Filter',
- 'audit_deleted_item' => 'Deleted Item',
- 'audit_deleted_item_name' => 'Name: :name',
- 'audit_table_user' => 'User',
- 'audit_table_event' => 'Event',
- 'audit_table_related' => 'Related Item or Detail',
- 'audit_table_date' => 'Activity Date',
- 'audit_date_from' => 'Date Range From',
- 'audit_date_to' => 'Date Range To',
+ 'audit' => 'Revisionslog',
+ 'audit_desc' => 'Denne revisionslog viser en liste over aktiviteter sporet i systemet. Denne liste er ufiltreret i modsætning til lignende aktivitetslister i systemet, hvor tilladelsesfiltre anvendes.',
+ 'audit_event_filter' => 'Event filter',
+ 'audit_event_filter_no_filter' => 'Intet filter',
+ 'audit_deleted_item' => 'Element slettet',
+ 'audit_deleted_item_name' => 'Navn: :name',
+ 'audit_table_user' => 'Bruger',
+ 'audit_table_event' => 'Hændelse',
+ 'audit_table_related' => 'Relateret element eller detalje',
+ 'audit_table_date' => 'Aktivitetsdato',
+ 'audit_date_from' => 'Datointerval fra',
+ 'audit_date_to' => 'Datointerval til',
// Role Settings
'roles' => 'Roller',
'role_access_api' => 'Tilgå system-API',
'role_manage_settings' => 'Administrer app-indstillinger',
'role_asset' => 'Tilladelser for medier og "assets"',
- 'roles_system_warning' => 'Be aware that access to any of the above three permissions can allow a user to alter their own privileges or the privileges of others in the system. Only assign roles with these permissions to trusted users.',
+ 'roles_system_warning' => 'Vær opmærksom på, at adgang til alle af de ovennævnte tre tilladelser, kan give en bruger mulighed for at ændre deres egne brugerrettigheder eller brugerrettigheder for andre i systemet. Tildel kun roller med disse tilladelser til betroede brugere.',
'role_asset_desc' => 'Disse tilladelser kontrollerer standardadgang til medier og "assets" i systemet. Tilladelser til bøger, kapitler og sider tilsidesætter disse tilladelser.',
'role_asset_admins' => 'Administratorer får automatisk adgang til alt indhold, men disse indstillinger kan vise eller skjule UI-indstillinger.',
'role_all' => 'Alle',
'user_profile' => 'Brugerprofil',
'users_add_new' => 'Tilføj ny bruger',
'users_search' => 'Søg efter brugere',
- 'users_latest_activity' => 'Latest Activity',
+ 'users_latest_activity' => 'Seneste aktivitet',
'users_details' => 'Brugeroplysninger',
'users_details_desc' => 'Angiv et visningsnavn og en E-Mail-adresse for denne bruger. E-Mail-adressen bruges til at logge ind på applikationen.',
'users_details_desc_no_email' => 'Sætter et visningsnavn for denne bruger, så andre kan genkende dem.',
'users_delete_named' => 'Slet bruger :userName',
'users_delete_warning' => 'Dette vil helt slette denne bruger med navnet \':userName\' fra systemet.',
'users_delete_confirm' => 'Er du sikker på, at du vil slette denne bruger?',
- 'users_migrate_ownership' => 'Migrate Ownership',
- 'users_migrate_ownership_desc' => 'Select a user here if you want another user to become the owner of all items currently owned by this user.',
- 'users_none_selected' => 'No user selected',
- 'users_delete_success' => 'User successfully removed',
+ 'users_migrate_ownership' => 'Overfør ejerskab',
+ 'users_migrate_ownership_desc' => 'Vælg en bruger her, hvis du vil have en anden bruger til at blive ejer af alle elementer, der i øjeblikket ejes af denne bruger.',
+ 'users_none_selected' => 'Ingen bruger valgt',
+ 'users_delete_success' => 'Brugeren blev fjernet',
'users_edit' => 'Rediger bruger',
'users_edit_profile' => 'Rediger profil',
'users_edit_success' => 'Bruger suscesfuldt opdateret',
'ar' => 'العربية',
'bg' => 'Bǎlgarski',
'bs' => 'Bosanski',
- 'ca' => 'Català',
+ 'ca' => 'Catalansk',
'cs' => 'Česky',
'da' => 'Dansk',
'de' => 'Deutsch (Sie)',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'Hebraisk',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'required_without' => ':attribute skal udfyldes når :values ikke er udfyldt.',
'required_without_all' => ':attribute skal udfyldes når ingen af :values er udfyldt.',
'same' => ':attribute og :other skal være ens.',
- 'safe_url' => 'The provided link may not be safe.',
+ 'safe_url' => 'Det angivne link kan være usikkert.',
'size' => [
'numeric' => ':attribute skal være :size.',
'file' => ':attribute skal være :size kilobytes.',
'bookshelf_delete' => 'hat das Bücherregal gelöscht',
'bookshelf_delete_notification' => 'Das Bücherregal wurde erfolgreich gelöscht',
+ // Favourites
+ 'favourite_add_notification' => '":name" wurde zu deinen Favoriten hinzugefügt',
+ 'favourite_remove_notification' => '":name" wurde aus Ihren Favoriten entfernt',
+
// Other
'commented_on' => 'hat einen Kommentar hinzugefügt',
'permissions_update' => 'hat die Berechtigungen aktualisiert',
'remove' => 'Entfernen',
'add' => 'Hinzufügen',
'fullscreen' => 'Vollbild',
+ 'favourite' => 'Favorit',
+ 'unfavourite' => 'Kein Favorit',
+ 'next' => 'Nächste',
+ 'previous' => 'Vorheriges',
// Sort Options
'sort_options' => 'Sortieroptionen',
'sort_ascending' => 'Aufsteigend sortieren',
'sort_descending' => 'Absteigend sortieren',
'sort_name' => 'Name',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Standard',
'sort_created_at' => 'Erstellungsdatum',
'sort_updated_at' => 'Aktualisierungsdatum',
'breadcrumb' => 'Brotkrumen',
// Header
+ 'header_menu_expand' => 'Header-Menü erweitern',
'profile_menu' => 'Profilmenü',
'view_profile' => 'Profil ansehen',
'edit_profile' => 'Profil bearbeiten',
// Layout tabs
'tab_info' => 'Info',
+ 'tab_info_label' => 'Tab: Sekundäre Informationen anzeigen',
'tab_content' => 'Inhalt',
+ 'tab_content_label' => 'Tab: Hauptinhalt anzeigen',
// Email Content
'email_action_help' => 'Sollte es beim Anklicken der Schaltfläche ":action_text" Probleme geben, öffnen Sie folgende URL in Ihrem Browser:',
'images' => 'Bilder',
'my_recent_drafts' => 'Meine kürzlichen Entwürfe',
'my_recently_viewed' => 'Kürzlich von mir angesehen',
+ 'my_most_viewed_favourites' => 'Meine meistgesehenen Favoriten',
+ 'my_favourites' => 'Meine Favoriten',
'no_pages_viewed' => 'Sie haben bisher keine Seiten angesehen',
'no_pages_recently_created' => 'Sie haben bisher keine Seiten angelegt',
'no_pages_recently_updated' => 'Sie haben bisher keine Seiten aktualisiert',
'search_permissions_set' => 'Berechtigungen gesetzt',
'search_created_by_me' => 'Von mir erstellt',
'search_updated_by_me' => 'Von mir aktualisiert',
- 'search_owned_by_me' => 'Owned by me',
+ 'search_owned_by_me' => 'Besitzt von mir',
'search_date_options' => 'Datums Optionen',
'search_updated_before' => 'Aktualisiert vor',
'search_updated_after' => 'Aktualisiert nach',
'404_page_not_found' => 'Seite nicht gefunden',
'sorry_page_not_found' => 'Entschuldigung. Die Seite, die Sie angefordert haben, wurde nicht gefunden.',
'sorry_page_not_found_permission_warning' => 'Wenn Sie erwartet haben, dass diese Seite existiert, haben Sie möglicherweise nicht die Berechtigung, sie anzuzeigen.',
+ 'image_not_found' => 'Bild nicht gefunden',
+ 'image_not_found_subtitle' => 'Entschuldigung. Das Bild, die Sie angefordert haben, wurde nicht gefunden.',
+ 'image_not_found_details' => 'Wenn Sie erwartet haben, dass dieses Bild existiert, könnte es gelöscht worden sein.',
'return_home' => 'Zurück zur Startseite',
'error_occurred' => 'Es ist ein Fehler aufgetreten',
'app_down' => ':appName befindet sich aktuell im Wartungsmodus.',
'app_homepage_desc' => 'Wählen Sie eine Seite als Startseite aus, die statt der Standardansicht angezeigt werden soll. Seitenberechtigungen werden für die ausgewählten Seiten ignoriert.',
'app_homepage_select' => 'Wählen Sie eine Seite aus',
'app_footer_links' => 'Fußzeilen-Links',
- 'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
+ 'app_footer_links_desc' => 'Fügen Sie Links hinzu, die innerhalb der Seitenfußzeile angezeigt werden. Diese werden am unteren Ende der meisten Seiten angezeigt, einschließlich derjenigen, die keinen Login benötigen. Sie können die Bezeichnung "trans::<key>" verwenden, um systemdefinierte Übersetzungen zu verwenden. Beispiel: Mit "trans::common.privacy_policy" wird der übersetzte Text "Privacy Policy" bereitgestellt, und "trans::common.terms_of_service" liefert den übersetzten Text "Terms of Service".',
'app_footer_links_label' => 'Link-Label',
'app_footer_links_url' => 'Link-URL',
'app_footer_links_add' => 'Fußzeilen-Link hinzufügen',
'ar' => 'العربية',
'bg' => 'Bulgarisch',
'bs' => 'Bosanski',
- 'ca' => 'Català',
+ 'ca' => 'Katalanisch',
'cs' => 'Česky',
'da' => 'Dänisch',
'de' => 'Deutsch (Sie)',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'Hebräisch',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'löscht Bücherregal',
'bookshelf_delete_notification' => 'Das Bücherregal wurde erfolgreich gelöscht',
+ // Favourites
+ 'favourite_add_notification' => '":name" wurde zu deinen Favoriten hinzugefügt',
+ 'favourite_remove_notification' => '":name" wurde aus Ihren Favoriten entfernt',
+
// Other
'commented_on' => 'kommentiert',
'permissions_update' => 'aktualisierte Berechtigungen',
'remove' => 'Entfernen',
'add' => 'Hinzufügen',
'fullscreen' => 'Vollbild',
+ 'favourite' => 'Favorit',
+ 'unfavourite' => 'Kein Favorit',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Sortieroptionen',
'sort_ascending' => 'Aufsteigend sortieren',
'sort_descending' => 'Absteigend sortieren',
'sort_name' => 'Name',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Standard',
'sort_created_at' => 'Erstellungsdatum',
'sort_updated_at' => 'Aktualisierungsdatum',
'breadcrumb' => 'Brotkrumen',
// Header
+ 'header_menu_expand' => 'Header-Menü erweitern',
'profile_menu' => 'Profilmenü',
'view_profile' => 'Profil ansehen',
'edit_profile' => 'Profil bearbeiten',
// Layout tabs
'tab_info' => 'Info',
+ 'tab_info_label' => 'Tab: Sekundäre Informationen anzeigen',
'tab_content' => 'Inhalt',
+ 'tab_content_label' => 'Tab: Hauptinhalt anzeigen',
// Email Content
'email_action_help' => 'Sollte es beim Anklicken der Schaltfläche ":action_text" Probleme geben, öffne die folgende URL in Deinem Browser:',
// Footer Link Options
// Not directly used but available for convenience to users.
- 'privacy_policy' => 'Datenschutzbestimmungen',
+ 'privacy_policy' => 'Datenschutzerklärung',
'terms_of_service' => 'Allgemeine Geschäftsbedingungen',
];
'images' => 'Bilder',
'my_recent_drafts' => 'Meine kürzlichen Entwürfe',
'my_recently_viewed' => 'Kürzlich von mir angesehen',
+ 'my_most_viewed_favourites' => 'Meine meistgesehenen Favoriten',
+ 'my_favourites' => 'Meine Favoriten',
'no_pages_viewed' => 'Du hast bisher keine Seiten angesehen.',
'no_pages_recently_created' => 'Du hast bisher keine Seiten angelegt.',
'no_pages_recently_updated' => 'Du hast bisher keine Seiten aktualisiert.',
'search_permissions_set' => 'Berechtigungen gesetzt',
'search_created_by_me' => 'Von mir erstellt',
'search_updated_by_me' => 'Von mir aktualisiert',
- 'search_owned_by_me' => 'Owned by me',
+ 'search_owned_by_me' => 'Besitzt von mir',
'search_date_options' => 'Datums Optionen',
'search_updated_before' => 'Aktualisiert vor',
'search_updated_after' => 'Aktualisiert nach',
'404_page_not_found' => 'Seite nicht gefunden',
'sorry_page_not_found' => 'Entschuldigung. Die Seite, die Du angefordert hast, wurde nicht gefunden.',
'sorry_page_not_found_permission_warning' => 'Wenn du erwartet hast, dass diese Seite existiert, hast du möglicherweise nicht die Berechtigung, sie anzuzeigen.',
+ 'image_not_found' => 'Bild nicht gefunden',
+ 'image_not_found_subtitle' => 'Entschuldigung. Das Bild, die Sie angefordert haben, wurde nicht gefunden.',
+ 'image_not_found_details' => 'Wenn Sie erwartet haben, dass dieses Bild existiert, könnte es gelöscht worden sein.',
'return_home' => 'Zurück zur Startseite',
'error_occurred' => 'Es ist ein Fehler aufgetreten',
'app_down' => ':appName befindet sich aktuell im Wartungsmodus.',
'app_homepage_desc' => 'Wähle eine Seite als Startseite aus, die statt der Standardansicht angezeigt werden soll. Seitenberechtigungen werden für die ausgewählten Seiten ignoriert.',
'app_homepage_select' => 'Wählen Sie eine Seite aus',
'app_footer_links' => 'Fußzeilen-Links',
- 'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
+ 'app_footer_links_desc' => 'Fügen Sie Links hinzu, die innerhalb der Seitenfußzeile angezeigt werden. Diese werden am unteren Ende der meisten Seiten angezeigt, einschließlich derjenigen, die keinen Login benötigen. Sie können die Bezeichnung "trans::<key>" verwenden, um systemdefinierte Übersetzungen zu verwenden. Beispiel: Mit "trans::common.privacy_policy" wird der übersetzte Text "Privacy Policy" bereitgestellt, und "trans::common.terms_of_service" liefert den übersetzten Text "Terms of Service".',
'app_footer_links_label' => 'Link-Label',
'app_footer_links_url' => 'Link-URL',
- 'app_footer_links_add' => 'Fußzeilen-Link hinzufügen',
+ 'app_footer_links_add' => 'Fußzeilenlink hinzufügen',
'app_disable_comments' => 'Kommentare deaktivieren',
'app_disable_comments_toggle' => 'Kommentare deaktivieren',
'app_disable_comments_desc' => 'Deaktiviert Kommentare über alle Seiten in der Anwendung. Vorhandene Kommentare werden nicht angezeigt.',
'ar' => 'العربية',
'bg' => 'Bulgarisch',
'bs' => 'Bosanski',
- 'ca' => 'Català',
+ 'ca' => 'Katalanisch',
'cs' => 'Česky',
'da' => 'Dänisch',
'de' => 'Deutsch (Sie)',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'deleted bookshelf',
'bookshelf_delete_notification' => 'Bookshelf Successfully Deleted',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'commented on',
'permissions_update' => 'updated permissions',
'remove' => 'Remove',
'add' => 'Add',
'fullscreen' => 'Fullscreen',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Sort Options',
'no_activity' => 'No activity to show',
'no_items' => 'No items available',
'back_to_top' => 'Back to top',
+ 'skip_to_main_content' => 'Skip to main content',
'toggle_details' => 'Toggle Details',
'toggle_thumbnails' => 'Toggle Thumbnails',
'details' => 'Details',
'breadcrumb' => 'Breadcrumb',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Profile Menu',
'view_profile' => 'View Profile',
'edit_profile' => 'Edit Profile',
// Layout tabs
'tab_info' => 'Info',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Content',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'If you’re having trouble clicking the ":actionText" button, copy and paste the URL below into your web browser:',
'images' => 'Images',
'my_recent_drafts' => 'My Recent Drafts',
'my_recently_viewed' => 'My Recently Viewed',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'You have not viewed any pages',
'no_pages_recently_created' => 'No pages have been recently created',
'no_pages_recently_updated' => 'No pages have been recently updated',
'export_html' => 'Contained Web File',
'export_pdf' => 'PDF File',
'export_text' => 'Plain Text File',
+ 'export_md' => 'Markdown File',
// Permissions and restrictions
'permissions' => 'Permissions',
'404_page_not_found' => 'Page Not Found',
'sorry_page_not_found' => 'Sorry, The page you were looking for could not be found.',
'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Return to home',
'error_occurred' => 'An Error Occurred',
'app_down' => ':appName is down right now',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'estante eliminado',
'bookshelf_delete_notification' => 'Estante eliminado correctamente',
+ // Favourites
+ 'favourite_add_notification' => '".name" ha sido añadido a sus favoritos',
+ 'favourite_remove_notification' => '".name" ha sido eliminado de sus favoritos',
+
// Other
'commented_on' => 'comentada el',
'permissions_update' => 'permisos actualizados',
'remove' => 'Remover',
'add' => 'Añadir',
'fullscreen' => 'Pantalla completa',
+ 'favourite' => 'Añadir a favoritos',
+ 'unfavourite' => 'Eliminar de favoritos',
+ 'next' => 'Siguiente',
+ 'previous' => 'Anterior',
// Sort Options
'sort_options' => 'Opciones de ordenación',
'sort_ascending' => 'Ordenar Ascendentemente',
'sort_descending' => 'Ordenar Descendentemente',
'sort_name' => 'Nombre',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Predeterminada',
'sort_created_at' => 'Fecha de Creación',
'sort_updated_at' => 'Fecha de Modificación',
'breadcrumb' => 'Rastro de migas de pan',
// Header
+ 'header_menu_expand' => 'Expandir el Menú de la Cabecera',
'profile_menu' => 'Menú de Perfil',
'view_profile' => 'Ver Perfil',
'edit_profile' => 'Editar Perfil',
// Layout tabs
'tab_info' => 'Información',
+ 'tab_info_label' => 'Pestaña: Mostrar Información Secundaria',
'tab_content' => 'Contenido',
+ 'tab_content_label' => 'Pestaña: Mostrar Contenido Primario',
// Email Content
'email_action_help' => 'Si está teniendo problemas clicando en el botón ":actionText", copie y pegue la siguiente URL en su navegador web:',
'images' => 'Imágenes',
'my_recent_drafts' => 'Mis borradores recientes',
'my_recently_viewed' => 'Mis visualizaciones recientes',
+ 'my_most_viewed_favourites' => 'Mis favoritos más vistos',
+ 'my_favourites' => 'Mis favoritos',
'no_pages_viewed' => 'No ha visto ninguna página',
'no_pages_recently_created' => 'Ninguna página ha sido creada recientemente',
'no_pages_recently_updated' => 'Ninguna página ha sido actualizada recientemente',
'404_page_not_found' => 'Página no encontrada',
'sorry_page_not_found' => 'Lo sentimos, la página a la que intenta acceder no pudo ser encontrada.',
'sorry_page_not_found_permission_warning' => 'Si esperaba que esta página existiera, puede que no tenga permiso para verla.',
+ 'image_not_found' => 'Imagen no encontrada',
+ 'image_not_found_subtitle' => 'Lo sentimos, no se pudo encontrar el archivo de imagen que estaba buscando.',
+ 'image_not_found_details' => 'Si esperaba que esta imagen existiera, podría haber sido eliminada.',
'return_home' => 'Volver a la página de inicio',
'error_occurred' => 'Ha ocurrido un error',
'app_down' => 'La aplicación :appName se encuentra caída en este momento',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'Estante borrado',
'bookshelf_delete_notification' => 'Estante borrado exitosamente',
+ // Favourites
+ 'favourite_add_notification' => '".name" se añadió a sus favoritos',
+ 'favourite_remove_notification' => '".name" se eliminó de sus favoritos',
+
// Other
'commented_on' => 'comentado',
'permissions_update' => 'permisos actualizados',
'remove' => 'Remover',
'add' => 'Agregar',
'fullscreen' => 'Pantalla completa',
+ 'favourite' => 'Favoritos',
+ 'unfavourite' => 'Eliminar de favoritos',
+ 'next' => 'Siguiente',
+ 'previous' => 'Anterior',
// Sort Options
'sort_options' => 'Opciones de Orden',
'sort_ascending' => 'Orden Ascendente',
'sort_descending' => 'Orden Descendente',
'sort_name' => 'Nombre',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Por defecto',
'sort_created_at' => 'Fecha de creación',
'sort_updated_at' => 'Fecha de actualización',
// Misc
'deleted_user' => 'Usuario borrado',
'no_activity' => 'Ninguna actividad para mostrar',
- 'no_items' => 'No hay items disponibles',
+ 'no_items' => 'No hay elementos disponibles',
'back_to_top' => 'Volver arriba',
'toggle_details' => 'Alternar detalles',
'toggle_thumbnails' => 'Alternar miniaturas',
'breadcrumb' => 'Miga de Pan',
// Header
+ 'header_menu_expand' => 'Expandir el Menú de Cabecera',
'profile_menu' => 'Menu del Perfil',
'view_profile' => 'Ver Perfil',
'edit_profile' => 'Editar Perfil',
// Layout tabs
'tab_info' => 'Información',
+ 'tab_info_label' => 'Pestaña: Mostrar Información Secundaria',
'tab_content' => 'Contenido',
+ 'tab_content_label' => 'Pestaña: Mostrar Contenido Primario',
// Email Content
'email_action_help' => 'Si está teniendo problemas haga click en el botón ":actionText", copie y pegue la siguiente URL en su navegador web:',
'images' => 'Imágenes',
'my_recent_drafts' => 'Mis borradores recientes',
'my_recently_viewed' => 'Mis visualizaciones recientes',
+ 'my_most_viewed_favourites' => 'Mis Favoritos Más Vistos',
+ 'my_favourites' => 'Mis Favoritos',
'no_pages_viewed' => 'Ud. no ha visto ninguna página',
'no_pages_recently_created' => 'Ninguna página ha sido creada recientemente',
'no_pages_recently_updated' => 'Ninguna página ha sido actualizada recientemente',
'search_permissions_set' => 'Permisos establecidos',
'search_created_by_me' => 'Creado por mí',
'search_updated_by_me' => 'Actualizado por mí',
- 'search_owned_by_me' => 'Owned by me',
+ 'search_owned_by_me' => 'De mi propiedad',
'search_date_options' => 'Opciones de fecha',
'search_updated_before' => 'Actualizado antes de',
'search_updated_after' => 'Actualizado después de',
'attachments_link_attached' => 'Enlace agregado exitosamente a la página',
'templates' => 'Plantillas',
'templates_set_as_template' => 'La Página es una plantilla',
- 'templates_explain_set_as_template' => 'Puede establecer esta página como plantilla para que el contenido pueda utilizarse para al crear otras páginas. Otris usuarios podrán utilizar esta plantilla si tienen permisos para ver de esta página.',
+ 'templates_explain_set_as_template' => 'Puede establecer esta página como plantilla para que el contenido pueda utilizarse al crear otras páginas. Otros usuarios podrán utilizar esta plantilla si tienen permisos para ver de esta página.',
'templates_replace_content' => 'Reemplazar el contenido de la página',
'templates_append_content' => 'Incorporar al fina del contenido de la página',
'templates_prepend_content' => 'Incorporar al principio del contenido de la página',
'404_page_not_found' => 'Página no encontrada',
'sorry_page_not_found' => 'Lo sentimos, la página que intenta acceder no pudo ser encontrada.',
'sorry_page_not_found_permission_warning' => 'Si esperaba que esta página existiera, puede que no tenga permiso para verla.',
+ 'image_not_found' => 'No se encuentra la imagen',
+ 'image_not_found_subtitle' => 'Lo siento, no se pudo encontrar la imagen que busca.',
+ 'image_not_found_details' => 'Si esperaba que esta imagen exista es probable que se haya eliminado.',
'return_home' => 'Volver al home',
'error_occurred' => 'Ha ocurrido un error',
'app_down' => 'La aplicación :appName se encuentra caída en este momento',
'app_custom_html_desc' => 'Cualquier contenido agregado aquí será agregado al final de la sección <head> de cada página. Esto es útil para sobreescribir estilos o agregar código para analíticas.',
'app_custom_html_disabled_notice' => 'El contenido personailzado para la cabecera HTML está deshabilitado en esta configuración para garantizar que cualquier cambio importante se pueda revertir.',
'app_logo' => 'Logo de la aplicación',
- 'app_logo_desc' => 'Esta imagen debería ser de 43px en altura. <br>Las imágenes grandes seán escaladas.',
+ 'app_logo_desc' => 'Esta imagen debería ser de 43px en altura. <br>Las imágenes grandes serán achicadas.',
'app_primary_color' => 'Color primario de la aplicación',
'app_primary_color_desc' => 'Esto debería ser un valor hexadecimal. <br>Deje el valor vacío para reiniciar al valor por defecto.',
'app_homepage' => 'Página de inicio de la Aplicación',
'maint' => 'Mantenimiento',
'maint_image_cleanup' => 'Limpiar imágenes',
'maint_image_cleanup_desc' => "Analizar contenido de páginas y revisiones para detectar cuáles imágenes y dibujos están en uso y cuáles son redundantes. Asegúrese de crear un respaldo completo de imágenes y base de datos antes de ejecutar esta tarea.",
- 'maint_delete_images_only_in_revisions' => 'Elimina también imágenes que sólo existen en antiguas revisiones de páginas',
+ 'maint_delete_images_only_in_revisions' => 'También elimina imágenes que sólo existen en antiguas revisiones de páginas',
'maint_image_cleanup_run' => 'Ejecutar limpieza',
'maint_image_cleanup_warning' => 'Se encontraron :count imágenes pontencialmente sin uso. Está seguro de que quiere eliminarlas?',
'maint_image_cleanup_success' => 'Se encontraron y se eliminaron :count imágenes pontencialmente sin uso!',
'recycle_bin_contents_empty' => 'La papelera de reciclaje está vacía',
'recycle_bin_empty' => 'Vaciar Papelera de reciclaje',
'recycle_bin_empty_confirm' => 'Esto destruirá permanentemente todos los elementos de la papelera de reciclaje, incluyendo el contenido existente en cada elemento. ¿Está seguro de que desea vaciar la papelera de reciclaje?',
- 'recycle_bin_destroy_confirm' => 'Esta acción eliminará permanentemente este elemento del sistema, junto con los elementos secundarios listados a continuación, y no podrá restaurar este contenido de nuevo. ¿Está seguro de que desea eliminar permanentemente este elemento?',
- 'recycle_bin_destroy_list' => 'Elementos a eliminar',
+ 'recycle_bin_destroy_confirm' => 'Esta acción eliminará permanentemente este elemento del sistema, junto con los elementos secundarios listados a continuación, y no podrá restaurar este contenido. ¿Está seguro de que desea eliminar permanentemente este elemento?',
+ 'recycle_bin_destroy_list' => 'Elementos a destruir',
'recycle_bin_restore_list' => 'Elementos a restaurar',
'recycle_bin_restore_confirm' => 'Esta acción restaurará el elemento eliminado, incluyendo cualquier elemento secundario, a su ubicación original. Si la ubicación original ha sido eliminada, y ahora está en la papelera de reciclaje, el elemento padre también tendrá que ser restaurado.',
'recycle_bin_restore_deleted_parent' => 'El padre de este elemento también ha sido eliminado. Estos permanecerán eliminados hasta que el padre también sea restaurado.',
- 'recycle_bin_destroy_notification' => 'Eliminados :count artículos de la papelera de reciclaje.',
- 'recycle_bin_restore_notification' => 'Restaurados :count artículos desde la papelera de reciclaje.',
+ 'recycle_bin_destroy_notification' => 'Eliminados :count elementos de la papelera de reciclaje.',
+ 'recycle_bin_restore_notification' => 'Restaurados :count elementos desde la papelera de reciclaje.',
// Audit Log
'audit' => 'Registro de Auditoría',
'users_delete_confirm' => '¿Está seguro que desea borrar este usuario?',
'users_migrate_ownership' => 'Cambiar Propietario',
'users_migrate_ownership_desc' => 'Seleccione un usuario aquí si desea que otro usuario se convierta en el dueño de todos los elementos que actualmente son propiedad de este usuario.',
- 'users_none_selected' => 'Usuario no seleccionado',
- 'users_delete_success' => 'El usuario se ha eliminado correctamente',
+ 'users_none_selected' => 'No hay usuario seleccionado',
+ 'users_delete_success' => 'El usuario fue eliminado correctamente',
'users_edit' => 'Editar Usuario',
'users_edit_profile' => 'Editar perfil',
'users_edit_success' => 'Usuario actualizado',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'deleted bookshelf',
'bookshelf_delete_notification' => 'Bookshelf Successfully Deleted',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'commented on',
'permissions_update' => 'updated permissions',
'remove' => 'Remove',
'add' => 'Add',
'fullscreen' => 'Fullscreen',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Sort Options',
'breadcrumb' => 'Breadcrumb',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Profile Menu',
'view_profile' => 'View Profile',
'edit_profile' => 'Edit Profile',
// Layout tabs
'tab_info' => 'Info',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Content',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'If you’re having trouble clicking the ":actionText" button, copy and paste the URL below into your web browser:',
'images' => 'Images',
'my_recent_drafts' => 'My Recent Drafts',
'my_recently_viewed' => 'My Recently Viewed',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'You have not viewed any pages',
'no_pages_recently_created' => 'No pages have been recently created',
'no_pages_recently_updated' => 'No pages have been recently updated',
'404_page_not_found' => 'Page Not Found',
'sorry_page_not_found' => 'Sorry, The page you were looking for could not be found.',
'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Return to home',
'error_occurred' => 'An Error Occurred',
'app_down' => ':appName is down right now',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'a supprimé l\'étagère',
'bookshelf_delete_notification' => 'Étagère supprimée avec succès',
+ // Favourites
+ 'favourite_add_notification' => '":name" a été ajouté dans vos favoris',
+ 'favourite_remove_notification' => '":name" a été supprimé de vos favoris',
+
// Other
'commented_on' => 'a commenté',
'permissions_update' => 'mettre à jour les autorisations',
'remove' => 'Enlever',
'add' => 'Ajouter',
'fullscreen' => 'Plein écran',
+ 'favourite' => 'Favoris',
+ 'unfavourite' => 'Supprimer des favoris',
+ 'next' => 'Suivant',
+ 'previous' => 'Précédent',
// Sort Options
'sort_options' => 'Options de tri',
'sort_ascending' => 'Tri ascendant',
'sort_descending' => 'Tri descendant',
'sort_name' => 'Nom',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Défaut',
'sort_created_at' => 'Date de création',
'sort_updated_at' => 'Date de mise à jour',
'breadcrumb' => 'Fil d\'Ariane',
// Header
+ 'header_menu_expand' => 'Développer le menu',
'profile_menu' => 'Menu du profil',
'view_profile' => 'Voir le profil',
'edit_profile' => 'Modifier le profil',
// Layout tabs
'tab_info' => 'Informations',
+ 'tab_info_label' => 'Onglet : Afficher les informations secondaires',
'tab_content' => 'Contenu',
+ 'tab_content_label' => 'Onglet : Afficher le contenu principal',
// Email Content
'email_action_help' => 'Si vous rencontrez des problèmes pour cliquer sur le bouton ":actionText", copiez et collez l\'adresse ci-dessous dans votre navigateur :',
'images' => 'Images',
'my_recent_drafts' => 'Mes brouillons récents',
'my_recently_viewed' => 'Vus récemment',
+ 'my_most_viewed_favourites' => 'Mes Favoris les plus vus',
+ 'my_favourites' => 'Mes favoris',
'no_pages_viewed' => 'Vous n\'avez rien visité récemment',
'no_pages_recently_created' => 'Aucune page créée récemment',
'no_pages_recently_updated' => 'Aucune page mise à jour récemment',
'search_permissions_set' => 'Ensemble d\'autorisations',
'search_created_by_me' => 'Créé par moi',
'search_updated_by_me' => 'Mis à jour par moi',
- 'search_owned_by_me' => 'Owned by me',
+ 'search_owned_by_me' => 'Créés par moi',
'search_date_options' => 'Recherche par date',
'search_updated_before' => 'Mis à jour avant',
'search_updated_after' => 'Mis à jour après',
'404_page_not_found' => 'Page non trouvée',
'sorry_page_not_found' => 'Désolé, cette page n\'a pas pu être trouvée.',
'sorry_page_not_found_permission_warning' => 'Si vous vous attendiez à ce que cette page existe, il se peut que vous n\'ayez pas l\'autorisation de la consulter.',
+ 'image_not_found' => 'Image non trouvée',
+ 'image_not_found_subtitle' => 'Désolé, l\'image que vous cherchez ne peut être trouvée.',
+ 'image_not_found_details' => 'Si vous vous attendiez à ce que cette image existe, elle pourrait avoir été supprimée.',
'return_home' => 'Retour à l\'accueil',
'error_occurred' => 'Une erreur est survenue',
'app_down' => ':appName n\'est pas en service pour le moment',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'Hébreu',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'deleted bookshelf',
'bookshelf_delete_notification' => 'מדף הספרים הוסר בהצלחה',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'commented on',
'permissions_update' => 'updated permissions',
'remove' => 'הסר',
'add' => 'הוסף',
'fullscreen' => 'Fullscreen',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Sort Options',
'breadcrumb' => 'Breadcrumb',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Profile Menu',
'view_profile' => 'הצג פרופיל',
'edit_profile' => 'ערוך פרופיל',
// Layout tabs
'tab_info' => 'מידע',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'תוכן',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'אם לא ניתן ללחות על כפתור ״:actionText״, יש להעתיק ולהדביק את הכתובת למטה אל דפדפן האינטרנט שלך:',
'images' => 'תמונות',
'my_recent_drafts' => 'הטיוטות האחרונות שלי',
'my_recently_viewed' => 'הנצפים לאחרונה שלי',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'לא צפית בדפים כלשהם',
'no_pages_recently_created' => 'לא נוצרו דפים לאחרונה',
'no_pages_recently_updated' => 'לא עודכנו דפים לאחרונה',
'404_page_not_found' => 'דף לא קיים',
'sorry_page_not_found' => 'מצטערים, הדף שחיפשת אינו קיים',
'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'בחזרה לדף הבית',
'error_occurred' => 'התרחשה שגיאה',
'app_down' => ':appName כרגע אינו זמין',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
--- /dev/null
+<?php
+/**
+ * Activity text strings.
+ * Is used for all the text within activity logs & notifications.
+ */
+return [
+
+ // Pages
+ 'page_create' => 'stvorena stranica',
+ 'page_create_notification' => 'Stranica je uspješno stvorena',
+ 'page_update' => 'ažurirana stranica',
+ 'page_update_notification' => 'Stranica je uspješno ažurirana',
+ 'page_delete' => 'izbrisana stranica',
+ 'page_delete_notification' => 'Stranica je uspješno izbrisana',
+ 'page_restore' => 'obnovljena stranica',
+ 'page_restore_notification' => 'Stranica je uspješno obnovljena',
+ 'page_move' => 'premještena stranica',
+
+ // Chapters
+ 'chapter_create' => 'stvoreno poglavlje',
+ 'chapter_create_notification' => 'Poglavlje je uspješno stvoreno',
+ 'chapter_update' => 'ažurirano poglavlje',
+ 'chapter_update_notification' => 'Poglavlje je uspješno ažurirano',
+ 'chapter_delete' => 'izbrisano poglavlje',
+ 'chapter_delete_notification' => 'Poglavlje je uspješno izbrisano',
+ 'chapter_move' => 'premiješteno poglavlje',
+
+ // Books
+ 'book_create' => 'stvorena knjiga',
+ 'book_create_notification' => 'Knjiga je uspješno stvorena',
+ 'book_update' => 'ažurirana knjiga',
+ 'book_update_notification' => 'Knjiga je uspješno ažurirana',
+ 'book_delete' => 'izbrisana knjiga',
+ 'book_delete_notification' => 'Knjiga je uspješno izbrisana',
+ 'book_sort' => 'razvrstana knjiga',
+ 'book_sort_notification' => 'Knjiga je uspješno razvrstana',
+
+ // Bookshelves
+ 'bookshelf_create' => 'stvorena polica za knjige',
+ 'bookshelf_create_notification' => 'Polica za knjige je uspješno stvorena',
+ 'bookshelf_update' => 'ažurirana polica za knjige',
+ 'bookshelf_update_notification' => 'Polica za knjige je uspješno ažurirana',
+ 'bookshelf_delete' => 'izbrisana polica za knjige',
+ 'bookshelf_delete_notification' => 'Polica za knjige je uspješno izbrisana',
+
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
+ // Other
+ 'commented_on' => 'komentirano',
+ 'permissions_update' => 'ažurirana dopuštenja',
+];
--- /dev/null
+<?php
+/**
+ * Authentication Language Lines
+ * The following language lines are used during authentication for various
+ * messages that we need to display to the user.
+ */
+return [
+
+ 'failed' => 'Ove vjerodajnice ne podudaraju se s našim zapisima.',
+ 'throttle' => 'Previše pokušaja prijave. Molimo vas da pokušate za :seconds sekundi.',
+
+ // Login & Register
+ 'sign_up' => 'Registrirajte se',
+ 'log_in' => 'Prijavite se',
+ 'log_in_with' => 'Prijavite se sa :socialDriver',
+ 'sign_up_with' => 'Registrirajte se sa :socialDriver',
+ 'logout' => 'Odjavite se',
+
+ 'name' => 'Ime',
+ 'username' => 'Korisničko ime',
+ 'email' => 'Email',
+ 'password' => 'Lozinka',
+ 'password_confirm' => 'Potvrdite lozinku',
+ 'password_hint' => 'Mora imati više od 7 znakova',
+ 'forgot_password' => 'Zaboravili ste lozinku?',
+ 'remember_me' => 'Zapamti me',
+ 'ldap_email_hint' => 'Molimo upišite mail korišten za ovaj račun.',
+ 'create_account' => 'Stvori račun',
+ 'already_have_account' => 'Imate li već račun?',
+ 'dont_have_account' => 'Nemate račun?',
+ 'social_login' => 'Social Login',
+ 'social_registration' => 'Social Registration',
+ 'social_registration_text' => 'Prijavite se putem drugih servisa.',
+
+ 'register_thanks' => 'Zahvaljujemo na registraciji!',
+ 'register_confirm' => 'Molimo, provjerite svoj email i kliknite gumb za potvrdu pristupa :appName.',
+ 'registrations_disabled' => 'Registracije su trenutno onemogućene',
+ 'registration_email_domain_invalid' => 'Ova e-mail adresa se ne može koristiti u ovoj aplikaciji',
+ 'register_success' => 'Hvala na prijavi! Sada ste registrirani i prijavljeni.',
+
+
+ // Password Reset
+ 'reset_password' => 'Promijenite lozinku',
+ 'reset_password_send_instructions' => 'Upišite svoju e-mail adresu kako biste primili poveznicu za promjenu lozinke.',
+ 'reset_password_send_button' => 'Pošalji poveznicu za promjenu lozinke',
+ 'reset_password_sent' => 'Poveznica za promjenu lozinke poslat će se na :email adresu ako je u našem sustavu.',
+ 'reset_password_success' => 'Vaša lozinka je uspješno promijenjena.',
+ 'email_reset_subject' => 'Promijenite svoju :appName lozinku',
+ 'email_reset_text' => 'Primili ste ovu poruku jer je zatražena promjena lozinke za vaš račun.',
+ 'email_reset_not_requested' => 'Ako niste tražili promjenu lozinke slobodno zanemarite ovu poruku.',
+
+
+ // Email Confirmation
+ 'email_confirm_subject' => 'Potvrdite svoju e-mail adresu na :appName',
+ 'email_confirm_greeting' => 'Hvala na prijavi :appName!',
+ 'email_confirm_text' => 'Molimo potvrdite svoju e-mail adresu klikom na donji gumb.',
+ 'email_confirm_action' => 'Potvrdi Email',
+ 'email_confirm_send_error' => 'Potvrda e-mail adrese je obavezna, ali sustav ne može poslati e-mail. Javite se administratoru kako bi provjerio vaš e-mail.',
+ 'email_confirm_success' => 'Vaš e-mail adresa je potvrđena!',
+ 'email_confirm_resent' => 'Ponovno je poslana potvrda. Molimo, provjerite svoj inbox.',
+
+ 'email_not_confirmed' => 'E-mail adresa nije potvrđena.',
+ 'email_not_confirmed_text' => 'Vaša e-mail adresa još nije potvrđena.',
+ 'email_not_confirmed_click_link' => 'Molimo, kliknite na poveznicu koju ste primili kratko nakon registracije.',
+ 'email_not_confirmed_resend' => 'Ako ne možete pronaći e-mail za postavljanje lozinke možete ga zatražiti ponovno ispunjavanjem ovog obrasca.',
+ 'email_not_confirmed_resend_button' => 'Ponovno pošalji e-mail potvrde',
+
+ // User Invite
+ 'user_invite_email_subject' => 'Pozvani ste pridružiti se :appName!',
+ 'user_invite_email_greeting' => 'Vaš račun je kreiran za vas na :appName',
+ 'user_invite_email_text' => 'Kliknite ispod da biste postavili račun i dobili pristup.',
+ 'user_invite_email_action' => 'Postavite lozinku',
+ 'user_invite_page_welcome' => 'Dobrodošli u :appName!',
+ 'user_invite_page_text' => 'Da biste postavili račun i dobili pristup trebate unijeti lozinku kojom ćete se ubuduće prijaviti na :appName.',
+ 'user_invite_page_confirm_button' => 'Potvrdite lozinku',
+ 'user_invite_success' => 'Lozinka je postavljena, možete pristupiti :appName!'
+];
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Common elements found throughout many areas of BookStack.
+ */
+return [
+
+ // Buttons
+ 'cancel' => 'Odustani',
+ 'confirm' => 'Potvrdi',
+ 'back' => 'Natrag',
+ 'save' => 'Spremi',
+ 'continue' => 'Nastavi',
+ 'select' => 'Odaberi',
+ 'toggle_all' => 'Prebaci sve',
+ 'more' => 'Više',
+
+ // Form Labels
+ 'name' => 'Ime',
+ 'description' => 'Opis',
+ 'role' => 'Uloga',
+ 'cover_image' => 'Naslovna slika',
+ 'cover_image_description' => 'Slika treba biti približno 440x250px.',
+
+ // Actions
+ 'actions' => 'Aktivnost',
+ 'view' => 'Pogled',
+ 'view_all' => 'Pogledaj sve',
+ 'create' => 'Stvori',
+ 'update' => 'Ažuriraj',
+ 'edit' => 'Uredi',
+ 'sort' => 'Razvrstaj',
+ 'move' => 'Makni',
+ 'copy' => 'Kopiraj',
+ 'reply' => 'Ponovi',
+ 'delete' => 'Izbriši',
+ 'delete_confirm' => 'Potvrdite brisanje',
+ 'search' => 'Traži',
+ 'search_clear' => 'Očisti pretragu',
+ 'reset' => 'Ponovno postavi',
+ 'remove' => 'Ukloni',
+ 'add' => 'Dodaj',
+ 'fullscreen' => 'Cijeli zaslon',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
+
+ // Sort Options
+ 'sort_options' => 'Razvrstaj opcije',
+ 'sort_direction_toggle' => 'Razvrstaj smjer prebacivanja',
+ 'sort_ascending' => 'Razvrstaj uzlazno',
+ 'sort_descending' => 'Razvrstaj silazno',
+ 'sort_name' => 'Ime',
+ 'sort_default' => 'Zadano',
+ 'sort_created_at' => 'Datum',
+ 'sort_updated_at' => 'Ažuriraj datum',
+
+ // Misc
+ 'deleted_user' => 'Izbrisani korisnik',
+ 'no_activity' => 'Nema aktivnosti za pregled',
+ 'no_items' => 'Nedostupno',
+ 'back_to_top' => 'Natrag na vrh',
+ 'toggle_details' => 'Prebaci detalje',
+ 'toggle_thumbnails' => 'Uključi minijature',
+ 'details' => 'Detalji',
+ 'grid_view' => 'Prikaz rešetke',
+ 'list_view' => 'Prikaz popisa',
+ 'default' => 'Zadano',
+ 'breadcrumb' => 'Breadcrumb',
+
+ // Header
+ 'header_menu_expand' => 'Proširi izbornik',
+ 'profile_menu' => 'Profil',
+ 'view_profile' => 'Vidi profil',
+ 'edit_profile' => 'Uredite profil',
+ 'dark_mode' => 'Tamni način',
+ 'light_mode' => 'Svijetli način',
+
+ // Layout tabs
+ 'tab_info' => 'Info',
+ 'tab_info_label' => 'Tab: pokaži sekundarne informacije',
+ 'tab_content' => 'Sadržaj',
+ 'tab_content_label' => 'Tab: pokaži primarni sadržaj',
+
+ // Email Content
+ 'email_action_help' => 'Ako imate poteškoća s klikom na gumb ":actionText", kopirajte i zalijepite donji URL u vaš preglednik.',
+ 'email_rights' => 'Sva prava pridržana',
+
+ // Footer Link Options
+ // Not directly used but available for convenience to users.
+ 'privacy_policy' => 'Politika privatnosti',
+ 'terms_of_service' => 'Uvjeti korištenja',
+];
--- /dev/null
+<?php
+/**
+ * Text used in custom JavaScript driven components.
+ */
+return [
+
+ // Image Manager
+ 'image_select' => 'Odabir slike',
+ 'image_all' => 'Sve',
+ 'image_all_title' => 'Vidi sve slike',
+ 'image_book_title' => 'Vidi slike dodane ovoj knjizi',
+ 'image_page_title' => 'Vidi slike dodane ovoj stranici',
+ 'image_search_hint' => 'Pretraži pomoću imena slike',
+ 'image_uploaded' => 'Učitano :uploadedDate',
+ 'image_load_more' => 'Učitaj više',
+ 'image_image_name' => 'Ime slike',
+ 'image_delete_used' => 'Ova slika korištena je na donjoj stranici.',
+ 'image_delete_confirm_text' => 'Jeste li sigurni da želite obrisati sliku?',
+ 'image_select_image' => 'Odaberi sliku',
+ 'image_dropzone' => 'Prebacite sliku ili kliknite ovdje za prijenos',
+ 'images_deleted' => 'Obrisane slike',
+ 'image_preview' => 'Pregled slike',
+ 'image_upload_success' => 'Slika je uspješno dodana',
+ 'image_update_success' => 'Detalji slike su uspješno ažurirani',
+ 'image_delete_success' => 'Slika je obrisana',
+ 'image_upload_remove' => 'Ukloni',
+
+ // Code Editor
+ 'code_editor' => 'Uredi kod',
+ 'code_language' => 'Jezik koda',
+ 'code_content' => 'Sadržaj koda',
+ 'code_session_history' => 'Povijest sesije',
+ 'code_save' => 'Spremi kod',
+];
--- /dev/null
+<?php
+/**
+ * Text used for 'Entities' (Document Structure Elements) such as
+ * Books, Shelves, Chapters & Pages
+ */
+return [
+
+ // Shared
+ 'recently_created' => 'Nedavno stvoreno',
+ 'recently_created_pages' => 'Nedavno stvorene stranice',
+ 'recently_updated_pages' => 'Nedavno ažurirane stranice',
+ 'recently_created_chapters' => 'Nedavno stvorena poglavlja',
+ 'recently_created_books' => 'Nedavno stvorene knjige',
+ 'recently_created_shelves' => 'Nedavno stvorene police',
+ 'recently_update' => 'Nedavno ažurirano',
+ 'recently_viewed' => 'Nedavno viđeno',
+ 'recent_activity' => 'Nedavna aktivnost',
+ 'create_now' => 'Stvori sada',
+ 'revisions' => 'Revizije',
+ 'meta_revision' => 'Revizija #:revisionCount',
+ 'meta_created' => 'Stvoreno :timeLength',
+ 'meta_created_name' => 'Stvoreno :timeLength od :user',
+ 'meta_updated' => 'Ažurirano :timeLength',
+ 'meta_updated_name' => 'Ažurirano :timeLength od :user',
+ 'meta_owned_name' => 'Vlasništvo :user',
+ 'entity_select' => 'Odaberi subjekt',
+ 'images' => 'Slike',
+ 'my_recent_drafts' => 'Nedavne skice',
+ 'my_recently_viewed' => 'Nedavno viđeno',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
+ 'no_pages_viewed' => 'Niste pogledali nijednu stranicu',
+ 'no_pages_recently_created' => 'Nema nedavno stvorenih stranica',
+ 'no_pages_recently_updated' => 'Nema nedavno ažuriranih stranica',
+ 'export' => 'Izvoz',
+ 'export_html' => 'Web File',
+ 'export_pdf' => 'PDF File',
+ 'export_text' => 'Text File',
+
+ // Permissions and restrictions
+ 'permissions' => 'Dopuštenja',
+ 'permissions_intro' => 'Jednom postavljene, ove dozvole bit će prioritetne ostalim dopuštenjima.',
+ 'permissions_enable' => 'Omogući dopuštenje za korištenje',
+ 'permissions_save' => 'Spremi dopuštenje',
+ 'permissions_owner' => 'Vlasnik',
+
+ // Search
+ 'search_results' => 'Pretraži rezultate',
+ 'search_total_results_found' => ':count rezultat|:count ukupno pronađenih rezultata',
+ 'search_clear' => 'Očisti pretragu',
+ 'search_no_pages' => 'Nijedna stranica ne podudara se s ovim pretraživanjem',
+ 'search_for_term' => 'Traži :term',
+ 'search_more' => 'Više rezultata',
+ 'search_advanced' => 'Napredno pretraživanje',
+ 'search_terms' => 'Pretraži pojmove',
+ 'search_content_type' => 'Vrsta sadržaja',
+ 'search_exact_matches' => 'Podudarnosti',
+ 'search_tags' => 'Označi pretragu',
+ 'search_options' => 'Opcije',
+ 'search_viewed_by_me' => 'Pregledano od mene',
+ 'search_not_viewed_by_me' => 'Nije pregledano od mene',
+ 'search_permissions_set' => 'Set dopuštenja',
+ 'search_created_by_me' => 'Stvoreno od mene',
+ 'search_updated_by_me' => 'Ažurirano od mene',
+ 'search_owned_by_me' => 'Moje vlasništvo',
+ 'search_date_options' => 'Opcije datuma',
+ 'search_updated_before' => 'Ažurirano prije',
+ 'search_updated_after' => 'Ažurirano nakon',
+ 'search_created_before' => 'Stvoreno prije',
+ 'search_created_after' => 'Stvoreno nakon',
+ 'search_set_date' => 'Datumi',
+ 'search_update' => 'Ažuriraj pretragu',
+
+ // Shelves
+ 'shelf' => 'Polica',
+ 'shelves' => 'Police',
+ 'x_shelves' => ':count polica|:count polica',
+ 'shelves_long' => 'Police za knjige',
+ 'shelves_empty' => 'Nijedna polica nije stvorena',
+ 'shelves_create' => 'Stvori novu policu',
+ 'shelves_popular' => 'Popularne police',
+ 'shelves_new' => 'Nove police',
+ 'shelves_new_action' => 'Nova polica',
+ 'shelves_popular_empty' => 'Najpopularnije police pojavit će se. ovdje.',
+ 'shelves_new_empty' => 'Nedavno stvorene police pojavit će se ovdje.',
+ 'shelves_save' => 'Spremi policu',
+ 'shelves_books' => 'Knjige na ovoj polici',
+ 'shelves_add_books' => 'Dodaj knjige na ovu policu',
+ 'shelves_drag_books' => 'Prebaci knjige na ovu policu',
+ 'shelves_empty_contents' => 'Ova polica još nema dodijeljene knjige',
+ 'shelves_edit_and_assign' => 'Uredi policu za dodavanje knjiga',
+ 'shelves_edit_named' => 'Uredi policu :name',
+ 'shelves_edit' => 'Uredi policu',
+ 'shelves_delete' => 'Izbriši policu',
+ 'shelves_delete_named' => 'Izbriši policu :name',
+ 'shelves_delete_explain' => "This will delete the bookshelf with the name ':name'. Contained books will not be deleted.",
+ 'shelves_delete_confirmation' => 'Jeste li sigurni da želite obrisati policu?',
+ 'shelves_permissions' => 'Dopuštenja za policu',
+ 'shelves_permissions_updated' => 'Ažurirana dopuštenja za policu',
+ 'shelves_permissions_active' => 'Aktivirana dopuštenja za policu',
+ 'shelves_copy_permissions_to_books' => 'Kopiraj dopuštenja za knjige',
+ 'shelves_copy_permissions' => 'Kopiraj dopuštenja',
+ 'shelves_copy_permissions_explain' => 'Ovo će promijeniti trenutna dopuštenja za policu i knjige u njoj. Prije aktivacije provjerite jesu li sve dopuštenja za ovu policu spremljena.',
+ 'shelves_copy_permission_success' => 'Dopuštenja za policu kopirana za :count knjiga',
+
+ // Books
+ 'book' => 'Knjiga',
+ 'books' => 'Knjige',
+ 'x_books' => ':count knjiga|:count knjiga',
+ 'books_empty' => 'Nijedna knjiga nije stvorena',
+ 'books_popular' => 'Popularne knjige',
+ 'books_recent' => 'Nedavne knjige',
+ 'books_new' => 'Nove knjige',
+ 'books_new_action' => 'Nova knjiga',
+ 'books_popular_empty' => 'Najpopularnije knjige pojavit će se ovdje.',
+ 'books_new_empty' => 'Najnovije knjige pojavit će se ovdje.',
+ 'books_create' => 'Stvori novu knjigu',
+ 'books_delete' => 'Izbriši knjigu',
+ 'books_delete_named' => 'Izbriši knjigu :bookName',
+ 'books_delete_explain' => 'Ovaj korak će izbrisati knjigu \':bookName\'. Izbrisati će sve stranice i poglavlja.',
+ 'books_delete_confirmation' => 'Jeste li sigurni da želite izbrisati ovu knjigu?',
+ 'books_edit' => 'Uredi knjigu',
+ 'books_edit_named' => 'Uredi knjigu :bookName',
+ 'books_form_book_name' => 'Ime knjige',
+ 'books_save' => 'Spremi knjigu',
+ 'books_permissions' => 'Dopuštenja za knjigu',
+ 'books_permissions_updated' => 'Ažurirana dopuštenja za knjigu',
+ 'books_empty_contents' => 'U ovoj knjizi još nema stranica ni poglavlja.',
+ 'books_empty_create_page' => 'Stvori novu stranicu',
+ 'books_empty_sort_current_book' => 'Razvrstaj postojeće knjige',
+ 'books_empty_add_chapter' => 'Dodaj poglavlje',
+ 'books_permissions_active' => 'Aktivna dopuštenja za knjigu',
+ 'books_search_this' => 'Traži knjigu',
+ 'books_navigation' => 'Navigacija knjige',
+ 'books_sort' => 'Razvrstaj sadržaj knjige',
+ 'books_sort_named' => 'Razvrstaj knjigu :bookName',
+ 'books_sort_name' => 'Razvrstaj po imenu',
+ 'books_sort_created' => 'Razvrstaj po datumu nastanka',
+ 'books_sort_updated' => 'Razvrstaj po datumu ažuriranja',
+ 'books_sort_chapters_first' => 'Prva poglavlja',
+ 'books_sort_chapters_last' => 'Zadnja poglavlja',
+ 'books_sort_show_other' => 'Pokaži ostale knjige',
+ 'books_sort_save' => 'Spremi novi poredak',
+
+ // Chapters
+ 'chapter' => 'Poglavlje',
+ 'chapters' => 'Poglavlja',
+ 'x_chapters' => ':count poglavlje|:count poglavlja',
+ 'chapters_popular' => 'Popularna poglavlja',
+ 'chapters_new' => 'Novo poglavlje',
+ 'chapters_create' => 'Stvori novo poglavlje',
+ 'chapters_delete' => 'Izbriši poglavlje',
+ 'chapters_delete_named' => 'Izbriši poglavlje :chapterName',
+ 'chapters_delete_explain' => 'Ovaj korak briše poglavlje \':chapterName\'. Sve stranice u njemu će biti izbrisane.',
+ 'chapters_delete_confirm' => 'Jeste li sigurni da želite izbrisati poglavlje?',
+ 'chapters_edit' => 'Uredi poglavlje',
+ 'chapters_edit_named' => 'Uredi poglavlje :chapterName',
+ 'chapters_save' => 'Spremi poglavlje',
+ 'chapters_move' => 'Premjesti poglavlje',
+ 'chapters_move_named' => 'Premjesti poglavlje :chapterName',
+ 'chapter_move_success' => 'Poglavlje premješteno u :bookName',
+ 'chapters_permissions' => 'Dopuštenja za poglavlje',
+ 'chapters_empty' => 'U ovom poglavlju nema stranica.',
+ 'chapters_permissions_active' => 'Aktivna dopuštenja za poglavlje',
+ 'chapters_permissions_success' => 'Ažurirana dopuštenja za poglavlje',
+ 'chapters_search_this' => 'Pretraži poglavlje',
+
+ // Pages
+ 'page' => 'Stranica',
+ 'pages' => 'Stranice',
+ 'x_pages' => ':count stranice|:count stranica',
+ 'pages_popular' => 'Popularne stranice',
+ 'pages_new' => 'Nova stranica',
+ 'pages_attachments' => 'Prilozi',
+ 'pages_navigation' => 'Navigacija stranice',
+ 'pages_delete' => 'Izbriši stranicu',
+ 'pages_delete_named' => 'Izbriši stranicu :pageName',
+ 'pages_delete_draft_named' => 'Izbriši nacrt stranice :pageName',
+ 'pages_delete_draft' => 'Izbriši nacrt stranice',
+ 'pages_delete_success' => 'Izbrisana stranica',
+ 'pages_delete_draft_success' => 'Izbrisan nacrt stranice',
+ 'pages_delete_confirm' => 'Jeste li sigurni da želite izbrisati stranicu?',
+ 'pages_delete_draft_confirm' => 'Jeste li sigurni da želite izbrisati nacrt stranice?',
+ 'pages_editing_named' => 'Uređivanje stranice :pageName',
+ 'pages_edit_draft_options' => 'Izrada skice',
+ 'pages_edit_save_draft' => 'Spremi nacrt',
+ 'pages_edit_draft' => 'Uredi nacrt stranice',
+ 'pages_editing_draft' => 'Uređivanja nacrta',
+ 'pages_editing_page' => 'Uređivanje stranice',
+ 'pages_edit_draft_save_at' => 'Nacrt spremljen kao',
+ 'pages_edit_delete_draft' => 'Izbriši nacrt',
+ 'pages_edit_discard_draft' => 'Odbaci nacrt',
+ 'pages_edit_set_changelog' => 'Postavi dnevnik promjena',
+ 'pages_edit_enter_changelog_desc' => 'Ukratko opišite promjene koje ste napravili',
+ 'pages_edit_enter_changelog' => 'Unesi dnevnik promjena',
+ 'pages_save' => 'Spremi stranicu',
+ 'pages_title' => 'Naslov stranice',
+ 'pages_name' => 'Ime stranice',
+ 'pages_md_editor' => 'Uređivač',
+ 'pages_md_preview' => 'Pregled',
+ 'pages_md_insert_image' => 'Umetni sliku',
+ 'pages_md_insert_link' => 'Umetni poveznicu',
+ 'pages_md_insert_drawing' => 'Umetni crtež',
+ 'pages_not_in_chapter' => 'Stranica nije u poglavlju',
+ 'pages_move' => 'Premjesti stranicu',
+ 'pages_move_success' => 'Stranica premještena u ":parentName"',
+ 'pages_copy' => 'Kopiraj stranicu',
+ 'pages_copy_desination' => 'Kopiraj odredište',
+ 'pages_copy_success' => 'Stranica je uspješno kopirana',
+ 'pages_permissions' => 'Dopuštenja stranice',
+ 'pages_permissions_success' => 'Ažurirana dopuštenja stranice',
+ 'pages_revision' => 'Revizija',
+ 'pages_revisions' => 'Revizija stranice',
+ 'pages_revisions_named' => 'Revizije stranice :pageName',
+ 'pages_revision_named' => 'Revizija stranice :pageName',
+ 'pages_revision_restored_from' => 'Oporavak iz #:id; :summary',
+ 'pages_revisions_created_by' => 'Stvoreno od',
+ 'pages_revisions_date' => 'Datum revizije',
+ 'pages_revisions_number' => '#',
+ 'pages_revisions_numbered' => 'Revizija #:id',
+ 'pages_revisions_numbered_changes' => 'Revizija #:id Promjene',
+ 'pages_revisions_changelog' => 'Dnevnik promjena',
+ 'pages_revisions_changes' => 'Promjene',
+ 'pages_revisions_current' => 'Trenutna verzija',
+ 'pages_revisions_preview' => 'Pregled',
+ 'pages_revisions_restore' => 'Vrati',
+ 'pages_revisions_none' => 'Ova stranica nema revizija',
+ 'pages_copy_link' => 'Kopiraj poveznicu',
+ 'pages_edit_content_link' => 'Uredi sadržaj',
+ 'pages_permissions_active' => 'Aktivna dopuštenja stranice',
+ 'pages_initial_revision' => 'Početno objavljivanje',
+ 'pages_initial_name' => 'Nova stranica',
+ 'pages_editing_draft_notification' => 'Uređujete nacrt stranice posljednji put spremljen :timeDiff.',
+ 'pages_draft_edited_notification' => 'Ova je stranica u međuvremenu ažurirana. Preporučujemo da odbacite ovaj nacrt.',
+ 'pages_draft_edit_active' => [
+ 'start_a' => ':count korisnika koji uređuju ovu stranicu',
+ 'start_b' => ':userName je počeo uređivati ovu stranicu',
+ 'time_a' => 'otkad je stranica posljednji put ažurirana',
+ 'time_b' => 'u zadnjih :minCount minuta',
+ 'message' => ':start :time. Pripazite na uzajamna ažuriranja!',
+ ],
+ 'pages_draft_discarded' => 'Nacrt je odbijen jer je uređivač ažurirao postoječi sadržaj',
+ 'pages_specific' => 'Predlošci stranice',
+ 'pages_is_template' => 'Predložak stranice',
+
+ // Editor Sidebar
+ 'page_tags' => 'Oznake stranice',
+ 'chapter_tags' => 'Oznake poglavlja',
+ 'book_tags' => 'Oznake knjiga',
+ 'shelf_tags' => 'Oznake polica',
+ 'tag' => 'Oznaka',
+ 'tags' => 'Tags',
+ 'tag_name' => 'Tag Name',
+ 'tag_value' => 'Oznaka vrijednosti (neobavezno)',
+ 'tags_explain' => "Add some tags to better categorise your content. \n You can assign a value to a tag for more in-depth organisation.",
+ 'tags_add' => 'Dodaj oznaku',
+ 'tags_remove' => 'Makni oznaku',
+ 'attachments' => 'Prilozi',
+ 'attachments_explain' => 'Dodajte datoteke ili poveznice za prikaz na vašoj stranici. Vidljive su na rubnoj oznaci stranice.',
+ 'attachments_explain_instant_save' => 'Promjene se automatski spremaju.',
+ 'attachments_items' => 'Dodane stavke',
+ 'attachments_upload' => 'Dodaj datoteku',
+ 'attachments_link' => 'Dodaj poveznicu',
+ 'attachments_set_link' => 'Postavi poveznicu',
+ 'attachments_delete' => 'Jeste li sigurni da želite izbrisati ovu stavku?',
+ 'attachments_dropzone' => 'Dodajte datoteke ili kliknite ovdje',
+ 'attachments_no_files' => 'Nijedna datoteka nije prenesena',
+ 'attachments_explain_link' => 'Možete dodati poveznicu ako ne želite prenijeti datoteku. Poveznica može voditi na drugu stranicu ili datoteku.',
+ 'attachments_link_name' => 'Ime poveznice',
+ 'attachment_link' => 'Poveznica na privitak',
+ 'attachments_link_url' => 'Poveznica na datoteku',
+ 'attachments_link_url_hint' => 'Url ili stranica ili datoteka',
+ 'attach' => 'Dodaj',
+ 'attachments_insert_link' => 'Dodaj poveznicu na stranicu',
+ 'attachments_edit_file' => 'Uredi datoteku',
+ 'attachments_edit_file_name' => 'Ime datoteke',
+ 'attachments_edit_drop_upload' => 'Dodaj datoteku ili klikni ovdje za prijenos',
+ 'attachments_order_updated' => 'Ažurirani popis priloga',
+ 'attachments_updated_success' => 'Ažurirani detalji priloga',
+ 'attachments_deleted' => 'Izbrisani prilozi',
+ 'attachments_file_uploaded' => 'Datoteka je uspješno prenešena',
+ 'attachments_file_updated' => 'Datoteka je uspješno ažurirana',
+ 'attachments_link_attached' => 'Poveznica je dodana na stranicu',
+ 'templates' => 'Predlošci',
+ 'templates_set_as_template' => 'Stranica je predložak',
+ 'templates_explain_set_as_template' => 'Ovu stranicu možete postaviti pomoću predloška koji možete koristiti tijekom stvaranja drugih stranica. Ostali korisnici će ga također moći koristiti ako imaju dopuštenje.',
+ 'templates_replace_content' => 'Zamjeni sadržaj stranice',
+ 'templates_append_content' => 'Dodaj sadržaju stranice',
+ 'templates_prepend_content' => 'Dodaj na sadržaj stranice',
+
+ // Profile View
+ 'profile_user_for_x' => 'Korisnik za :time',
+ 'profile_created_content' => 'Stvoreni sadržaj',
+ 'profile_not_created_pages' => ':userName nije kreirao nijednu stranicu',
+ 'profile_not_created_chapters' => ':userName nije kreirao nijedno poglavlje',
+ 'profile_not_created_books' => ':userName nije kreirao nijednu knjigu',
+ 'profile_not_created_shelves' => ':userName nije kreirao nijednu policu',
+
+ // Comments
+ 'comment' => 'Komentar',
+ 'comments' => 'Komentari',
+ 'comment_add' => 'Dodaj komentar',
+ 'comment_placeholder' => 'Komentar ostavi ovdje',
+ 'comment_count' => '{0} Nema komentara|{1} 1 Komentar|[2,*] :count Komentara',
+ 'comment_save' => 'Spremi komentar',
+ 'comment_saving' => 'Spremanje komentara',
+ 'comment_deleting' => 'Brisanje komentara',
+ 'comment_new' => 'Novi komentar',
+ 'comment_created' => 'komentirano :createDiff',
+ 'comment_updated' => 'Ažurirano :updateDiff od :username',
+ 'comment_deleted_success' => 'Izbrisani komentar',
+ 'comment_created_success' => 'Dodani komentar',
+ 'comment_updated_success' => 'Ažurirani komentar',
+ 'comment_delete_confirm' => 'Jeste li sigurni da želite izbrisati ovaj komentar?',
+ 'comment_in_reply_to' => 'Odgovor na :commentId',
+
+ // Revision
+ 'revision_delete_confirm' => 'Jeste li sigurni da želite izbrisati ovaj ispravak?',
+ 'revision_restore_confirm' => 'Jeste li sigurni da želite vratiti ovaj ispravak? Trenutni sadržaj će biti zamijenjen.',
+ 'revision_delete_success' => 'Izbrisani ispravak',
+ 'revision_cannot_delete_latest' => 'Posljednji ispravak se ne može izbrisati.'
+];
--- /dev/null
+<?php
+/**
+ * Text shown in error messaging.
+ */
+return [
+
+ // Permissions
+ 'permission' => 'Nemate dopuštenje za pristup traženoj stranici.',
+ 'permissionJson' => 'Nemate potrebno dopuštenje.',
+
+ // Auth
+ 'error_user_exists_different_creds' => 'Korisnik s mailom :email već postoji, ali s drugom vjerodajnicom.',
+ 'email_already_confirmed' => 'Email je već potvrđen, pokušajte se logirati.',
+ 'email_confirmation_invalid' => 'Ova vjerodajnica nije valjana ili je već bila korištena. Pokušajte se ponovno registrirati.',
+ 'email_confirmation_expired' => 'Ova vjerodajnica je istekla. Poslan je novi email za pristup.',
+ 'email_confirmation_awaiting' => 'Email adresa za račun koji se koristi mora biti potvrđen',
+ 'ldap_fail_anonymous' => 'LDAP pristup nije uspio zbog anonimnosti',
+ 'ldap_fail_authed' => 'LDAP pristup nije uspio',
+ 'ldap_extension_not_installed' => 'LDAP PHP ekstenzija nije instalirana',
+ 'ldap_cannot_connect' => 'Nemoguće pristupiti ldap serveru, problem s mrežom',
+ 'saml_already_logged_in' => 'Već ste prijavljeni',
+ 'saml_user_not_registered' => 'Korisnik :name nije registriran i automatska registracija je onemogućena',
+ 'saml_no_email_address' => 'Nismo pronašli email adresu za ovog korisnika u vanjskim sustavima',
+ 'saml_invalid_response_id' => 'Sustav za autentifikaciju nije prepoznat. Ovaj problem možda je nastao zbog vraćanja nakon prijave.',
+ 'saml_fail_authed' => 'Prijava pomoću :system nije uspjela zbog neuspješne autorizacije',
+ 'social_no_action_defined' => 'Nije definirana nijedna radnja',
+ 'social_login_bad_response' => "Error received during :socialAccount login: \n:error",
+ 'social_account_in_use' => 'Ovaj :socialAccount račun se već koristi. Pokušajte se prijaviti pomoću :socialAccount računa.',
+ 'social_account_email_in_use' => 'Ovaj mail :email se već koristi. Ako već imate naš račun možete se prijaviti pomoću :socialAccount računa u postavkama vašeg profila.',
+ 'social_account_existing' => 'Ovaj :socialAccount je već dodan u vaš profil.',
+ 'social_account_already_used_existing' => 'Ovaj :socialAccount već koristi drugi korisnik.',
+ 'social_account_not_used' => 'Ovaj :socialAccount račun ne koristi nijedan korisnik. Dodajte ga u postavke svog profila.',
+ 'social_account_register_instructions' => 'Ako nemate račun možete se registrirati pomoću :socialAccount opcija.',
+ 'social_driver_not_found' => 'Nije pronađeno',
+ 'social_driver_not_configured' => 'Postavke vašeg :socialAccount računa nisu ispravno postavljene.',
+ 'invite_token_expired' => 'Vaša pozivnica je istekla. Pokušajte ponovno postaviti lozinku.',
+
+ // System
+ 'path_not_writable' => 'Datoteka :filePath ne može se prenijeti. Učinite je lakše prepoznatljivom vašem serveru.',
+ 'cannot_get_image_from_url' => 'Nemoguće preuzeti sliku sa :url',
+ 'cannot_create_thumbs' => 'Provjerite imate li instaliranu GD PHP ekstenziju.',
+ 'server_upload_limit' => 'Prevelika količina za server. Pokušajte prenijeti manju veličinu.',
+ 'uploaded' => 'Prevelika količina za server. Pokušajte prenijeti manju veličinu.',
+ 'image_upload_error' => 'Problem s prenosom slike',
+ 'image_upload_type_error' => 'Nepodržani format slike',
+ 'file_upload_timeout' => 'Isteklo vrijeme za prijenos datoteke.',
+
+ // Attachments
+ 'attachment_not_found' => 'Prilozi nisu pronađeni',
+
+ // Pages
+ 'page_draft_autosave_fail' => 'Problem sa spremanjem nacrta. Osigurajte stabilnu internetsku vezu.',
+ 'page_custom_home_deletion' => 'Stranica označena kao naslovnica ne može se izbrisati',
+
+ // Entities
+ 'entity_not_found' => 'Nije pronađeno',
+ 'bookshelf_not_found' => 'Polica nije pronađena',
+ 'book_not_found' => 'Knjiga nije pronađena',
+ 'page_not_found' => 'Stranica nije pronađena',
+ 'chapter_not_found' => 'Poglavlje nije pronađeno',
+ 'selected_book_not_found' => 'Odabrana knjiga nije pronađena',
+ 'selected_book_chapter_not_found' => 'Odabrane knjige ili poglavlja nisu pronađena',
+ 'guests_cannot_save_drafts' => 'Gosti ne mogu spremiti nacrte',
+
+ // Users
+ 'users_cannot_delete_only_admin' => 'Ne možete izbrisati',
+ 'users_cannot_delete_guest' => 'Ne možete izbrisati',
+
+ // Roles
+ 'role_cannot_be_edited' => 'Ne može se urediti',
+ 'role_system_cannot_be_deleted' => 'Sistemske postavke ne možete izbrisati',
+ 'role_registration_default_cannot_delete' => 'Ne može se izbrisati',
+ 'role_cannot_remove_only_admin' => 'Učinite drugog korisnika administratorom prije uklanjanja ove administratorske uloge.',
+
+ // Comments
+ 'comment_list' => 'Pogreška prilikom dohvaćanja komentara.',
+ 'cannot_add_comment_to_draft' => 'Ne možete ostaviti komentar na ovaj nacrt.',
+ 'comment_add' => 'Greška prilikom dodavanja ili ažuriranja komentara.',
+ 'comment_delete' => 'Greška prilikom brisanja komentara.',
+ 'empty_comment' => 'Ne možete ostaviti prazan komentar.',
+
+ // Error pages
+ '404_page_not_found' => 'Stranica nije pronađena',
+ 'sorry_page_not_found' => 'Žao nam je, stranica koju tražite nije pronađena.',
+ 'sorry_page_not_found_permission_warning' => 'Ako smatrate da ova stranica još postoji, ali je ne vidite, moguće je da nemate omogućen pristup.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
+ 'return_home' => 'Povratak na početno',
+ 'error_occurred' => 'Došlo je do pogreške',
+ 'app_down' => ':appName trenutno nije dostupna',
+ 'back_soon' => 'Uskoro će se vratiti.',
+
+ // API errors
+ 'api_no_authorization_found' => 'Nije pronađena autorizacija',
+ 'api_bad_authorization_format' => 'Pogreška prilikom autorizacije',
+ 'api_user_token_not_found' => 'Format autorizacije nije podržan',
+ 'api_incorrect_token_secret' => 'Netočan API token',
+ 'api_user_no_api_permission' => 'Vlasnik API tokena nema potrebna dopuštenja',
+ 'api_user_token_expired' => 'Autorizacija je istekla',
+
+ // Settings & Maintenance
+ 'maintenance_test_email_failure' => 'Pogreška prilikom slanja testnog email:',
+
+];
--- /dev/null
+<?php
+/**
+ * Pagination Language Lines
+ * The following language lines are used by the paginator library to build
+ * the simple pagination links.
+ */
+return [
+
+ 'previous' => '« Prethodno',
+ 'next' => 'Sljedeće »',
+
+];
--- /dev/null
+<?php
+/**
+ * Password Reminder Language Lines
+ * The following language lines are the default lines which match reasons
+ * that are given by the password broker for a password update attempt has failed.
+ */
+return [
+
+ 'password' => 'Lozinka mora imati najmanje 8 znakova i biti potvrđena.',
+ 'user' => "We can't find a user with that e-mail address.",
+ 'token' => 'Ponovno postavljanje lozinke nemoguće putem ove adrese.',
+ 'sent' => 'Na vašu email adresu poslana je poveznica za ponovno postavljanje!',
+ 'reset' => 'Vaša je lozinka ponovno postavljena!',
+
+];
--- /dev/null
+<?php
+/**
+ * Settings text strings
+ * Contains all text strings used in the general settings sections of BookStack
+ * including users and roles.
+ */
+return [
+
+ // Common Messages
+ 'settings' => 'Postavke',
+ 'settings_save' => 'Spremi postavke',
+ 'settings_save_success' => 'Postavke spremljene',
+
+ // App Settings
+ 'app_customization' => 'Prilagođavanje',
+ 'app_features_security' => 'Značajke & Sigurnost',
+ 'app_name' => 'Ime aplikacije',
+ 'app_name_desc' => 'Ime je vidljivo u zaglavlju i svakoj sistemskoj poruci.',
+ 'app_name_header' => 'Prikaži ime u zaglavlju',
+ 'app_public_access' => 'Javni pristup',
+ 'app_public_access_desc' => 'Omogućavanje ove postavke pristup sadržaju imat će svi posjetitelji BookStack čak i ako nisu prijavljeni.',
+ 'app_public_access_desc_guest' => 'Javni pristup može se urediti putem opcije "Gost".',
+ 'app_public_access_toggle' => 'Dozvoli javni pristup',
+ 'app_public_viewing' => 'Dozvoljen javni pristup?',
+ 'app_secure_images' => 'Visoka razina sigurnosti prijenosa slika',
+ 'app_secure_images_toggle' => 'Omogući visoku sigurnost prijenosa slika',
+ 'app_secure_images_desc' => 'Zbog specifične izvedbe sve su slike javne. Osigurajte da indeksi direktorija nisu omogućeni kako bi se spriječio neovlašten pristup.',
+ 'app_editor' => 'Uređivač stranice',
+ 'app_editor_desc' => 'Odaberite uređivače stranica',
+ 'app_custom_html' => 'Prilagođeni HTML sadržaj',
+ 'app_custom_html_desc' => 'Sav sadržaj dodan ovdje bit će umetnut na dno <glavne> stranice. To je korisno za stiliziranje i dodavanje analitičkog koda.',
+ 'app_custom_html_disabled_notice' => 'Prilagođeni HTML je onemogućen kako bi se osiguralo vraćanje promjena u slučaju kvara.',
+ 'app_logo' => 'Logo aplikacije',
+ 'app_logo_desc' => 'Slika smije biti najviše 43px u visinu. <br>Velike slike će biti smanjene.',
+ 'app_primary_color' => 'Primarna boja aplikacije',
+ 'app_primary_color_desc' => 'Postavlja primarnu boju za aplikaciju uključujući natpis, gumbe i veze.',
+ 'app_homepage' => 'Glavna stranica aplikacije',
+ 'app_homepage_desc' => 'Odaberite prikaz svoje glavne stranice umjesto već zadane. Za odabrane stranice ne vrijede zadana dopuštenja.',
+ 'app_homepage_select' => 'Odaberi stranicu',
+ 'app_footer_links' => 'Podnožje',
+ 'app_footer_links_desc' => 'Odaberite poveznice koje će biti vidljive u podnožju većina stranica čak i na nekima koje ne zahtijevaju prijavu. Na primjer, oznaku "trans::common.privacy_policy" možete koristiti za sistemski definirani prijevod teksta "Politika Privatnosti", a za "Uvjete korištenja" možete koristiti "trans::common.terms_of_service".',
+ 'app_footer_links_label' => 'Oznaka veze',
+ 'app_footer_links_url' => 'Oznaka URL',
+ 'app_footer_links_add' => 'Dodaj vezu na podnožje',
+ 'app_disable_comments' => 'Onemogući komentare',
+ 'app_disable_comments_toggle' => 'Onemogući komentare',
+ 'app_disable_comments_desc' => 'Onemogući komentare za sve stranice u aplikaciji. <br> Postojeći komentari nisu prikazani.',
+
+ // Color settings
+ 'content_colors' => 'Boja sadržaja',
+ 'content_colors_desc' => 'Postavljanje boja za sve elemente stranice. Preporuča se odabir boja čija je svjetlina slična zadanim bojama.',
+ 'bookshelf_color' => 'Boja police',
+ 'book_color' => 'Boja knjige',
+ 'chapter_color' => 'Boja poglavlja',
+ 'page_color' => 'Boja stranice',
+ 'page_draft_color' => 'Boja nacrta',
+
+ // Registration Settings
+ 'reg_settings' => 'Registracija',
+ 'reg_enable' => 'Omogući registraciju',
+ 'reg_enable_toggle' => 'Omogući registraciju',
+ 'reg_enable_desc' => 'Ako je omogućeno korisnik se može sam registrirati nakon čega će mu biti dodijeljena jedna od korisničkih uloga.',
+ 'reg_default_role' => 'Zadaj ulogu korisnika nakon registracije',
+ 'reg_enable_external_warning' => 'Gornja opcija se zanemaruje ako postoji LDAP ili SAML autorifikacija. Korisnički računi za nepostojeće članove automatski će se kreirati ako je vanjska provjera autentičnosti bila uspješna.',
+ 'reg_email_confirmation' => 'Potvrda e maila',
+ 'reg_email_confirmation_toggle' => 'Zahtjev za potvrdom e maila',
+ 'reg_confirm_email_desc' => 'Ako postoje ograničenja domene potvrda e maila će se zahtijevati i ova će se opcija zanemariti.',
+ 'reg_confirm_restrict_domain' => 'Ograničenja domene',
+ 'reg_confirm_restrict_domain_desc' => 'Unesite popis email domena kojima želite ograničiti registraciju i odvojite ih zarezom. Korisnicima će se slati email prije interakcije s aplikacijom. <br> Uzmite u obzir da će korisnici moći koristiti druge e mail adrese nakon uspješne registracije.',
+ 'reg_confirm_restrict_domain_placeholder' => 'Bez ograničenja',
+
+ // Maintenance settings
+ 'maint' => 'Održavanje',
+ 'maint_image_cleanup' => 'Čišćenje slika',
+ 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.",
+ 'maint_delete_images_only_in_revisions' => 'Izbriši slike koje postoje u prijašnjim revizijama',
+ 'maint_image_cleanup_run' => 'Pokreni čišćenje',
+ 'maint_image_cleanup_warning' => ':count moguće neiskorištene slike. Jeste li sigurni da želite izbrisati ove slike?',
+ 'maint_image_cleanup_success' => ':count moguće neiskorištene slike su pronađene i izbrisane!',
+ 'maint_image_cleanup_nothing_found' => 'Nema neiskorištenih slika, Ništa nije izbrisano!',
+ 'maint_send_test_email' => 'Pošalji testni Email',
+ 'maint_send_test_email_desc' => 'Na ovaj način šaljete testni Email na adresu navedenu u vašem profilu.',
+ 'maint_send_test_email_run' => 'Pošalji testni email',
+ 'maint_send_test_email_success' => 'Email je poslan na :address',
+ 'maint_send_test_email_mail_subject' => 'Testni email',
+ 'maint_send_test_email_mail_greeting' => 'Email se može koristiti!',
+ 'maint_send_test_email_mail_text' => 'Čestitamo! Ako ste primili ovaj e mail znači da ćete ga moći koristiti.',
+ 'maint_recycle_bin_desc' => 'Izbrisane police, knjige, poglavlja i stranice poslane su u Recycle bin i mogu biti vraćene ili trajno izbrisane. Starije stavke bit će automatski izbrisane nakon nekog vremena što ovisi o konfiguraciji sustava.',
+ 'maint_recycle_bin_open' => 'Otvori Recycle Bin',
+
+ // Recycle Bin
+ 'recycle_bin' => 'Recycle Bin',
+ 'recycle_bin_desc' => 'Ovdje možete vratiti izbrisane stavke ili ih trajno ukloniti iz sustava. Popis nije filtriran kao što su to popisi u kojima su omogućeni filteri.',
+ 'recycle_bin_deleted_item' => 'Izbrisane stavke',
+ 'recycle_bin_deleted_by' => 'Izbrisano od',
+ 'recycle_bin_deleted_at' => 'Vrijeme brisanja',
+ 'recycle_bin_permanently_delete' => 'Trajno izbrisano',
+ 'recycle_bin_restore' => 'Vrati',
+ 'recycle_bin_contents_empty' => 'Recycle Bin je prazan',
+ 'recycle_bin_empty' => 'Isprazni Recycle Bin',
+ 'recycle_bin_empty_confirm' => 'Ovo će trajno obrisati sve stavke u Recycle Bin i sadržaje povezane s njima. Jeste li sigurni da želite isprazniti Recycle Bin?',
+ 'recycle_bin_destroy_confirm' => 'Ovom radnjom ćete trajno izbrisati ovu stavku i nećete je više moći vratiti. Želite li je trajno izbrisati?',
+ 'recycle_bin_destroy_list' => 'Stavke koje treba izbrisati',
+ 'recycle_bin_restore_list' => 'Stavke koje treba vratiti',
+ 'recycle_bin_restore_confirm' => 'Ova radnja vraća izbrisane stavke i njene podređene elemente na prvobitnu lokaciju. Ako je nadređena stavka izbrisana i nju treba vratiti.',
+ 'recycle_bin_restore_deleted_parent' => 'S obzirom da je nadređena stavka obrisana najprije treba vratiti nju.',
+ 'recycle_bin_destroy_notification' => 'Ukupno izbrisane :count stavke iz Recycle Bin',
+ 'recycle_bin_restore_notification' => 'Ukupno vraćene :count stavke iz Recycle Bin',
+
+ // Audit Log
+ 'audit' => 'Dnevnik revizije',
+ 'audit_desc' => 'Ovaj dnevnik revizije prikazuje popis aktivnosti zabilježene u sustavu. Ovaj popis nije definiran budući da nisu postavljeni filteri.',
+ 'audit_event_filter' => 'Filter događaja',
+ 'audit_event_filter_no_filter' => 'Bez filtera',
+ 'audit_deleted_item' => 'Izbrisane stavke',
+ 'audit_deleted_item_name' => 'Ime: :name',
+ 'audit_table_user' => 'Korisnik',
+ 'audit_table_event' => 'Događaj',
+ 'audit_table_related' => 'Povezana stavka ili detalj',
+ 'audit_table_date' => 'Datum aktivnosti',
+ 'audit_date_from' => 'Rangiraj datum od',
+ 'audit_date_to' => 'Rangiraj datum do',
+
+ // Role Settings
+ 'roles' => 'Uloge',
+ 'role_user_roles' => 'Uloge korisnika',
+ 'role_create' => 'Stvori novu ulogu',
+ 'role_create_success' => 'Uloga uspješno stvorena',
+ 'role_delete' => 'Izbriši ulogu',
+ 'role_delete_confirm' => 'Ovo će izbrisati ulogu povezanu s imenom \':roleName\'.',
+ 'role_delete_users_assigned' => 'Ova uloga dodijeljena je :userCount. Ako želite premjestiti korisnike iz ove uloge odaberite novu ulogu u nastavku.',
+ 'role_delete_no_migration' => "Don't migrate users",
+ 'role_delete_sure' => 'Jeste li sigurni da želite obrisati ovu ulogu?',
+ 'role_delete_success' => 'Uloga je uspješno izbrisana',
+ 'role_edit' => 'Uredi ulogu',
+ 'role_details' => 'Detalji uloge',
+ 'role_name' => 'Ime uloge',
+ 'role_desc' => 'Kratki opis uloge',
+ 'role_external_auth_id' => 'Autorizacija',
+ 'role_system' => 'Dopuštenja sustava',
+ 'role_manage_users' => 'Upravljanje korisnicima',
+ 'role_manage_roles' => 'Upravljanje ulogama i dopuštenjima',
+ 'role_manage_entity_permissions' => 'Upravljanje dopuštenjima nad knjigama, poglavljima i stranicama',
+ 'role_manage_own_entity_permissions' => 'Upravljanje dopuštenjima vlastitih knjiga, poglavlja i stranica',
+ 'role_manage_page_templates' => 'Upravljanje predlošcima stranica',
+ 'role_access_api' => 'API pristup',
+ 'role_manage_settings' => 'Upravljanje postavkama aplikacija',
+ 'role_asset' => 'Upravljanje vlasništvom',
+ 'roles_system_warning' => 'Uzmite u obzir da pristup bilo kojem od ovih dopuštenja dozvoljavate korisniku upravljanje dopuštenjima ostalih u sustavu. Ova dopuštenja dodijelite pouzdanim korisnicima.',
+ 'role_asset_desc' => 'Ova dopuštenja kontroliraju zadane pristupe. Dopuštenja za knjige, poglavlja i stranice ih poništavaju.',
+ 'role_asset_admins' => 'Administratori automatski imaju pristup svim sadržajima, ali ove opcije mogu prikazati ili sakriti korisnička sučelja.',
+ 'role_all' => 'Sve',
+ 'role_own' => 'Vlastito',
+ 'role_controlled_by_asset' => 'Kontrolirano od strane vlasnika',
+ 'role_save' => 'Spremi ulogu',
+ 'role_update_success' => 'Uloga uspješno ažurirana',
+ 'role_users' => 'Korisnici u ovoj ulozi',
+ 'role_users_none' => 'Trenutno nijedan korisnik nije u ovoj ulozi',
+
+ // Users
+ 'users' => 'Korisnici',
+ 'user_profile' => 'Profil korisnika',
+ 'users_add_new' => 'Dodajte novog korisnika',
+ 'users_search' => 'Pretražite korisnike',
+ 'users_latest_activity' => 'Zadnje aktivnosti',
+ 'users_details' => 'Detalji korisnika',
+ 'users_details_desc' => 'Postavite prikaz imena i email adrese za ovog korisnika. Email adresa koristit će se za prijavu u aplikaciju.',
+ 'users_details_desc_no_email' => 'Postavite prikaz imena ovog korisnika da ga drugi mogu prepoznati.',
+ 'users_role' => 'Uloge korisnika',
+ 'users_role_desc' => 'Odaberite koje će uloge biti dodijeljene ovom korisniku. Ako korisnik ima više uloga njihova će se dopuštenja prilagoditi.',
+ 'users_password' => 'Lozinka korisnika',
+ 'users_password_desc' => 'Postavite lozinku za prijavu u aplikaciju. Mora imati najmanje 6 znakova.',
+ 'users_send_invite_text' => 'Možete odabrati slanje e maila korisniku i dozvoliti mu da postavi svoju lozinku ili vi to možete učiniti za njega.',
+ 'users_send_invite_option' => 'Pošaljite pozivnicu korisniku putem emaila',
+ 'users_external_auth_id' => 'Vanjska autorizacija',
+ 'users_external_auth_id_desc' => 'Ovaj ID koristi se za komunikaciju s vanjskim sustavom za autorizaciju.',
+ 'users_password_warning' => 'Ispunite dolje samo ako želite promijeniti lozinku.',
+ 'users_system_public' => 'Ovaj korisnik predstavlja bilo kojeg gosta. Dodjeljuje se automatski.',
+ 'users_delete' => 'Izbrišite korisnika',
+ 'users_delete_named' => 'Izbrišite korisnika :userName',
+ 'users_delete_warning' => 'Ovo će ukloniti korisnika \':userName\' iz sustava.',
+ 'users_delete_confirm' => 'Jeste li sigurni da želite izbrisati ovog korisnika?',
+ 'users_migrate_ownership' => 'Premjestite vlasništvo',
+ 'users_migrate_ownership_desc' => 'Ovdje odaberite korisnika kojem ćete dodijeliti vlasništvo i sve stavke povezane s njim.',
+ 'users_none_selected' => 'Nije odabran nijedan korisnik',
+ 'users_delete_success' => 'Korisnik je uspješno premješten',
+ 'users_edit' => 'Uredite korisnika',
+ 'users_edit_profile' => 'Uredite profil',
+ 'users_edit_success' => 'Korisnik je uspješno ažuriran',
+ 'users_avatar' => 'Korisnički avatar',
+ 'users_avatar_desc' => 'Odaberite sliku koja će predstavljati korisnika. Maksimalno 256px.',
+ 'users_preferred_language' => 'Prioritetni jezik',
+ 'users_preferred_language_desc' => 'Ova će opcija promijeniti jezik korisničkog sučelja. Neće utjecati na sadržaj.',
+ 'users_social_accounts' => 'Računi društvenih mreža',
+ 'users_social_accounts_info' => 'Ovdje možete povezati račun s onim na društvenim mrežama za bržu i lakšu prijavu. Ako se odspojite ovdje to neće utjecati na prethodnu autorizaciju. Na postavkama računa vaše društvene mreže možete opozvati pristup.',
+ 'users_social_connect' => 'Poveži račun',
+ 'users_social_disconnect' => 'Odvoji račun',
+ 'users_social_connected' => ':socialAccount račun je uspješno dodan vašem profilu.',
+ 'users_social_disconnected' => ':socialAccount račun je uspješno odvojen od vašeg profila.',
+ 'users_api_tokens' => 'API tokeni',
+ 'users_api_tokens_none' => 'Nijedan API token nije stvoren za ovog korisnika',
+ 'users_api_tokens_create' => 'Stvori token',
+ 'users_api_tokens_expires' => 'Isteklo',
+ 'users_api_tokens_docs' => 'API dokumentacija',
+
+ // API Tokens
+ 'user_api_token_create' => 'Stvori API token',
+ 'user_api_token_name' => 'Ime',
+ 'user_api_token_name_desc' => 'Imenujte svoj token na način da prepoznate njegovu svrhu.',
+ 'user_api_token_expiry' => 'Datum isteka',
+ 'user_api_token_expiry_desc' => 'Postavite datum kada token istječe. Ostavljanjem ovog polja praznim automatski se postavlja dugoročno razdoblje.',
+ 'user_api_token_create_secret_message' => 'Odmah nakon kreiranja tokena prikazat će se "Token ID" i "Token Secret". To će se prikazati samo jednom i zato preporučujemo da ga spremite na sigurno.',
+ 'user_api_token_create_success' => 'API token uspješno kreiran',
+ 'user_api_token_update_success' => 'API token uspješno ažuriran',
+ 'user_api_token' => 'API token',
+ 'user_api_token_id' => 'Token ID',
+ 'user_api_token_id_desc' => 'Ovaj sistemski generiran identifikator ne može se uređivati i bit će potreban pri API zahtjevima.',
+ 'user_api_token_secret' => 'Token Secret',
+ 'user_api_token_secret_desc' => 'Ovaj sistemski generirani Token Secret trebat ćete za API zahtjev. Prikazuje se samo prvi put i zato ga spremite na sigurno.',
+ 'user_api_token_created' => 'Token kreiran :timeAgo',
+ 'user_api_token_updated' => 'Token ažuriran :timeAgo',
+ 'user_api_token_delete' => 'Izbriši token',
+ 'user_api_token_delete_warning' => 'Ovo će potpuno izbrisati API token naziva \':tokenName\' iz našeg sustava.',
+ 'user_api_token_delete_confirm' => 'Jeste li sigurni da želite izbrisati ovaj API token?',
+ 'user_api_token_delete_success' => 'API token uspješno izbrisan',
+
+ //! If editing translations files directly please ignore this in all
+ //! languages apart from en. Content will be auto-copied from en.
+ //!////////////////////////////////
+ 'language_select' => [
+ 'en' => 'English',
+ 'ar' => 'العربية',
+ 'bg' => 'Bǎlgarski',
+ 'bs' => 'Bosanski',
+ 'ca' => 'Català',
+ 'cs' => 'Česky',
+ 'da' => 'Dansk',
+ 'de' => 'Deutsch (Sie)',
+ 'de_informal' => 'Deutsch (Du)',
+ 'es' => 'Español',
+ 'es_AR' => 'Español Argentina',
+ 'fr' => 'Français',
+ 'he' => 'עברית',
+ 'hr' => 'Hrvatski',
+ 'hu' => 'Magyar',
+ 'id' => 'Bahasa Indonesia',
+ 'it' => 'Italian',
+ 'ja' => '日本語',
+ 'ko' => '한국어',
+ 'lv' => 'Latviešu Valoda',
+ 'nl' => 'Nederlands',
+ 'nb' => 'Norsk (Bokmål)',
+ 'pl' => 'Polski',
+ 'pt' => 'Português',
+ 'pt_BR' => 'Português do Brasil',
+ 'ru' => 'Русский',
+ 'sk' => 'Slovensky',
+ 'sl' => 'Slovenščina',
+ 'sv' => 'Svenska',
+ 'tr' => 'Türkçe',
+ 'uk' => 'Українська',
+ 'vi' => 'Tiếng Việt',
+ 'zh_CN' => '简体中文',
+ 'zh_TW' => '繁體中文',
+ ]
+ //!////////////////////////////////
+];
--- /dev/null
+<?php
+/**
+ * Validation Lines
+ * The following language lines contain the default error messages used by
+ * the validator class. Some of these rules have multiple versions such
+ * as the size rules. Feel free to tweak each of these messages here.
+ */
+return [
+
+ // Standard laravel validation lines
+ 'accepted' => ':attribute mora biti prihvaćen.',
+ 'active_url' => ':attribute nema valjan URL.',
+ 'after' => ':attribute mora biti nakon :date.',
+ 'alpha' => ':attribute može sadržavati samo slova.',
+ 'alpha_dash' => ':attribute može sadržavati samo slova, brojeve, crtice i donje crtice.',
+ 'alpha_num' => ':attribute može sadržavati samo slova i brojeve.',
+ 'array' => ':attribute mora biti niz.',
+ 'before' => ':attribute mora biti prije :date.',
+ 'between' => [
+ 'numeric' => ':attribute mora biti između :min i :max.',
+ 'file' => ':attribute mora biti između :min i :max kilobajta.',
+ 'string' => ':attribute mora biti između :min i :max znakova.',
+ 'array' => ':attribute mora biti između :min i :max stavki',
+ ],
+ 'boolean' => ':attribute mora biti točno ili netočno.',
+ 'confirmed' => ':attribute potvrde se ne podudaraju.',
+ 'date' => ':attribute nema valjani datum.',
+ 'date_format' => ':attribute ne odgovara formatu :format.',
+ 'different' => ':attribute i :other se moraju razlikovati.',
+ 'digits' => ':attribute mora biti :digits znakova.',
+ 'digits_between' => ':attribute mora biti između :min i :max znamenki.',
+ 'email' => ':attribute mora biti valjana email adresa.',
+ 'ends_with' => ':attribute mora završiti s :values',
+ 'filled' => ':attribute polje je obavezno.',
+ 'gt' => [
+ 'numeric' => ':attribute mora biti veći od :value.',
+ 'file' => ':attribute mora biti veći od :value kilobajta.',
+ 'string' => ':attribute mora biti veći od :value znakova',
+ 'array' => ':attribute mora biti veći od :value stavki.',
+ ],
+ 'gte' => [
+ 'numeric' => ':attribute mora biti veći ili jednak :value.',
+ 'file' => ':attribute mora biti veći ili jednak :value kilobajta.',
+ 'string' => ':attribute mora biti veći ili jednak :value znakova.',
+ 'array' => ':attribute mora imati :value stavki ili više.',
+ ],
+ 'exists' => 'Odabrani :attribute ne vrijedi.',
+ 'image' => ':attribute mora biti slika.',
+ 'image_extension' => ':attribute mora imati valjanu i podržanu ekstenziju.',
+ 'in' => 'Odabrani :attribute ne vrijedi.',
+ 'integer' => ':attribute mora biti cijeli broj.',
+ 'ip' => ':attribute mora biti valjana IP adresa.',
+ 'ipv4' => ':attribute mora biti valjana IPv4 adresa.',
+ 'ipv6' => ':attribute mora biti valjana IPv6 adresa.',
+ 'json' => ':attribute mora biti valjani JSON niz.',
+ 'lt' => [
+ 'numeric' => ':attribute mora biti manji od :value.',
+ 'file' => ':attribute mora biti manji od :value kilobajta.',
+ 'string' => ':attribute mora biti manji od :value znakova.',
+ 'array' => ':attribute mora biti manji od :value stavki.',
+ ],
+ 'lte' => [
+ 'numeric' => ':attribute mora biti manji ili jednak :value.',
+ 'file' => ':attribute mora biti manji ili jednak :value kilobajta.',
+ 'string' => ':attribute mora biti manji ili jednak :value znakova.',
+ 'array' => ':attribute mora imati više od :value stavki.',
+ ],
+ 'max' => [
+ 'numeric' => ':attribute ne smije biti veći od :max.',
+ 'file' => ':attribute ne smije biti veći od :max kilobajta.',
+ 'string' => ':attribute ne smije biti duži od :max znakova.',
+ 'array' => ':attribute ne smije imati više od :max stavki.',
+ ],
+ 'mimes' => ':attribute mora biti datoteka tipa: :values.',
+ 'min' => [
+ 'numeric' => ':attribute mora biti najmanje :min.',
+ 'file' => ':attribute mora imati najmanje :min kilobajta.',
+ 'string' => ':attribute mora imati najmanje :min znakova.',
+ 'array' => ':attribute mora imati najmanje :min stavki.',
+ ],
+ 'not_in' => 'Odabrani :attribute ne vrijedi.',
+ 'not_regex' => 'Format :attribute nije valjan.',
+ 'numeric' => ':attribute mora biti broj.',
+ 'regex' => 'Format :attribute nije valjan.',
+ 'required' => ':attribute polje je obavezno.',
+ 'required_if' => 'Polje :attribute je obavezno kada :other je :value.',
+ 'required_with' => 'Polje :attribute je potrebno kada :values je sadašnjost.',
+ 'required_with_all' => 'Polje :attribute je potrebno kada :values je sadašnjost.',
+ 'required_without' => 'Polje :attribute je potrebno kada :values nije sadašnjost.',
+ 'required_without_all' => 'Polje :attribute je potrebno kada ništa od :values nije sadašnjost.',
+ 'same' => ':attribute i :other se moraju podudarati.',
+ 'safe_url' => 'Navedena veza možda nije sigurna.',
+ 'size' => [
+ 'numeric' => ':attribute mora biti :size.',
+ 'file' => ':attribute mora biti :size kilobajta.',
+ 'string' => ':attribute mora biti :size znakova.',
+ 'array' => ':attribute mora sadržavati :size stavki.',
+ ],
+ 'string' => ':attribute mora biti niz.',
+ 'timezone' => ':attribute mora biti valjan.',
+ 'unique' => ':attribute se već koristi.',
+ 'url' => 'Format :attribute nije valjan.',
+ 'uploaded' => 'Datoteka se ne može prenijeti. Server možda ne prihvaća datoteke te veličine.',
+
+ // Custom validation lines
+ 'custom' => [
+ 'password-confirm' => [
+ 'required_with' => 'Potrebna potvrda lozinke',
+ ],
+ ],
+
+ // Custom validation attributes
+ 'attributes' => [],
+];
'bookshelf_delete' => 'törölte a könyvespolcot:',
'bookshelf_delete_notification' => 'Könyvespolc sikeresen törölve',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'megjegyzést fűzött hozzá:',
'permissions_update' => 'updated permissions',
'remove' => 'Eltávolítás',
'add' => 'Hozzáadás',
'fullscreen' => 'Teljes képernyő',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Rendezési beállítások',
'breadcrumb' => 'Morzsa',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Profil menü',
'view_profile' => 'Profil megtekintése',
'edit_profile' => 'Profil szerkesztése',
// Layout tabs
'tab_info' => 'Információ',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Tartalom',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Probléma esetén a lenti ":actionText" gombra kell kattintani, majd ki kell másolni a lenti webcímet és be kell illeszteni egy böngészőbe:',
'images' => 'Képek',
'my_recent_drafts' => 'Legutóbbi vázlataim',
'my_recently_viewed' => 'Általam legutóbb megtekintett',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Még nincsenek általam megtekintett oldalak',
'no_pages_recently_created' => 'Nincsenek legutóbb létrehozott oldalak',
'no_pages_recently_updated' => 'Nincsenek legutóbb frissített oldalak',
'404_page_not_found' => 'Oldal nem található',
'sorry_page_not_found' => 'Sajnáljuk, a keresett oldal nem található.',
'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Vissza a kezdőlapra',
'error_occurred' => 'Hiba örtént',
'app_down' => ':appName jelenleg nem üzemel',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
return [
// Pages
- 'page_create' => 'halaman dibuat',
+ 'page_create' => 'telah membuat halaman',
'page_create_notification' => 'Halaman Berhasil dibuat',
'page_update' => 'halaman diperbaharui',
- 'page_update_notification' => 'Berhasil mengupdate halaman',
+ 'page_update_notification' => 'Halaman Berhasil Diperbarui',
'page_delete' => 'halaman dihapus',
'page_delete_notification' => 'Berhasil menghapus halaman',
'page_restore' => 'halaman telah dipulihkan',
'chapter_create' => 'membuat bab',
'chapter_create_notification' => 'Bab berhasil dibuat',
'chapter_update' => 'bab diperbaharui',
- 'chapter_update_notification' => 'Bab berhasil diupdate',
+ 'chapter_update_notification' => 'Bab Berhasil Dipebarui',
'chapter_delete' => 'hapus bab',
'chapter_delete_notification' => 'Bab berhasil dihapus',
'chapter_move' => 'bab dipindahkan',
'book_create' => 'membuat buku',
'book_create_notification' => 'Buku berhasil dibuat',
'book_update' => 'update buku',
- 'book_update_notification' => 'Buku berhasil diupdate',
+ 'book_update_notification' => 'Buku Berhasil Diperbarui',
'book_delete' => 'hapus buku',
'book_delete_notification' => 'Buku berhasil dihapus',
- 'book_sort' => 'urutkan buku',
+ 'book_sort' => 'buku yang diurutkan',
'book_sort_notification' => 'Buku berhasil diurutkan',
// Bookshelves
'bookshelf_create' => 'membuat rak',
'bookshelf_create_notification' => 'Rak berhasil dibuat',
'bookshelf_update' => 'update rak',
- 'bookshelf_update_notification' => 'Rak berhasil diupdate',
+ 'bookshelf_update_notification' => 'Rak Berhasil Diperbarui',
'bookshelf_delete' => 'hapus rak buku',
'bookshelf_delete_notification' => 'Rak berhasil dihapus',
+ // Favourites
+ 'favourite_add_notification' => '":name" telah ditambahkan ke favorit Anda',
+ 'favourite_remove_notification' => '":name" telah dihapus dari favorit Anda',
+
// Other
'commented_on' => 'berkomentar pada',
- 'permissions_update' => 'perbaharui izin',
+ 'permissions_update' => 'izin diperbarui',
];
'remove' => 'Hapus',
'add' => 'Tambah',
'fullscreen' => 'Layar Penuh',
+ 'favourite' => 'Favorit',
+ 'unfavourite' => 'Tidak favorit',
+ 'next' => 'Lanjut',
+ 'previous' => 'Sebelumnya',
// Sort Options
'sort_options' => 'Sortir Pilihan',
'breadcrumb' => 'Breadcrumb',
// Header
+ 'header_menu_expand' => 'Perluas Menu Tajuk',
'profile_menu' => 'Profile Menu',
'view_profile' => 'Tampilkan profil',
'edit_profile' => 'Sunting Profil',
// Layout tabs
'tab_info' => 'Informasi',
+ 'tab_info_label' => 'Tab Menampilkan Informasi Sekunder',
'tab_content' => 'Konten',
+ 'tab_content_label' => 'Tab Menampilkan Informasi Utama',
// Email Content
'email_action_help' => 'Jika Anda mengalami masalah saat mengklik tombol ":actionText", salin dan tempel URL di bawah ini ke browser web Anda:',
'images' => 'Gambar-gambar',
'my_recent_drafts' => 'Draf Terbaru Saya',
'my_recently_viewed' => 'Baru saja saya lihat',
+ 'my_most_viewed_favourites' => 'Favorit Saya yang Paling Banyak Dilihat',
+ 'my_favourites' => 'Favoritku',
'no_pages_viewed' => 'Anda belum melihat halaman apa pun',
'no_pages_recently_created' => 'Tidak ada halaman yang baru saja dibuat',
'no_pages_recently_updated' => 'Tidak ada halaman yang baru-baru ini diperbarui',
'books_delete_explain' => 'Ini akan menghapus buku dengan nama \': bookName\'. Semua halaman dan bab akan dihapus.',
'books_delete_confirmation' => 'Apakah Anda yakin ingin menghapus buku ini?',
'books_edit' => 'Edit Buku',
- 'books_edit_named' => 'Edit Buku :bookName',
+ 'books_edit_named' => 'Sunting Buku :bookName',
'books_form_book_name' => 'Nama Buku',
'books_save' => 'Simpan Buku',
'books_permissions' => 'Izin Buku',
'chapters_delete_explain' => 'Ini akan menghapus chapter dengan nama \':chapterName\'. Semua halaman yang ada dalam bab ini juga akan dihapus.',
'chapters_delete_confirm' => 'Anda yakin ingin menghapus bab ini?',
'chapters_edit' => 'Edit Bab',
- 'chapters_edit_named' => 'Edit Bab :chapterName',
+ 'chapters_edit_named' => 'Sunting Bab :chapterName',
'chapters_save' => 'Simpan Bab',
'chapters_move' => 'Pindahkan Bab',
'chapters_move_named' => 'Pindahkan Bab :chapterName',
'pages_delete_draft_success' => 'Halaman draf dihapus',
'pages_delete_confirm' => 'Anda yakin ingin menghapus halaman ini?',
'pages_delete_draft_confirm' => 'Anda yakin ingin menghapus halaman draf ini?',
- 'pages_editing_named' => 'Mengedit Halaman :pageName',
+ 'pages_editing_named' => 'Menyunting Halaman :pageName',
'pages_edit_draft_options' => 'Opsi Draf',
'pages_edit_save_draft' => 'Simpan Draf',
'pages_edit_draft' => 'Edit Halaman Draf',
'pages_edit_draft_save_at' => 'Draf disimpan pada ',
'pages_edit_delete_draft' => 'Hapus Draf',
'pages_edit_discard_draft' => 'Buang Draf',
- 'pages_edit_set_changelog' => 'Setel Changelog',
+ 'pages_edit_set_changelog' => 'Atur Changelog',
'pages_edit_enter_changelog_desc' => 'Masukkan deskripsi singkat tentang perubahan yang Anda buat',
'pages_edit_enter_changelog' => 'Masuk ke Changelog',
'pages_save' => 'Simpan Halaman',
'pages_revisions_restore' => 'Mengembalikan',
'pages_revisions_none' => 'Halaman ini tidak memiliki revisi',
'pages_copy_link' => 'Salin tautan',
- 'pages_edit_content_link' => 'Edit Konten',
+ 'pages_edit_content_link' => 'Sunting Konten',
'pages_permissions_active' => 'Izin Halaman Aktif',
'pages_initial_revision' => 'Penerbitan awal',
'pages_initial_name' => 'Halaman Baru',
- 'pages_editing_draft_notification' => 'Anda sedang mengedit draf yang terakhir disimpan :timeDiff.',
+ 'pages_editing_draft_notification' => 'Anda sedang menyunting konsep yang terakhir disimpan :timeDiff.',
'pages_draft_edited_notification' => 'Halaman ini telah diperbarui sejak saat itu. Anda disarankan untuk membuang draf ini.',
'pages_draft_edit_active' => [
'start_a' => ':count pengguna sudah mulai mengedit halaman ini',
- 'start_b' => ':userName sudah mulai mengedit halaman ini',
- 'time_a' => 'perubahan di sini disimpan secara instan',
+ 'start_b' => ':userName telah memulai menyunting halaman ini',
+ 'time_a' => 'semenjak halaman terakhir diperbarui',
'time_b' => 'di akhir :minCount menit',
'message' => ':start :time. Berhati-hatilah untuk tidak menimpa pembaruan satu sama lain!',
],
- 'pages_draft_discarded' => 'Draf dibuang, Editor telah diperbarui dengan konten halaman saat ini',
+ 'pages_draft_discarded' => 'Konsep dibuang, Penyunting telah diperbarui dengan konten halaman saat ini',
'pages_specific' => 'Halaman Tertentu',
'pages_is_template' => 'Template Halaman',
'tags_add' => 'Tambahkan tag lain',
'tags_remove' => 'Hapus tag ini',
'attachments' => 'Lampiran',
- 'attachments_explain' => 'Unggah beberapa file atau lampirkan beberapa tautan untuk ditampilkan di laman Anda. Ini terlihat di sidebar halaman.',
+ 'attachments_explain' => 'Unggah beberapa berkas atau lampirkan beberapa tautan untuk ditampilkan di laman Anda. Ini terlihat di sidebar halaman.',
'attachments_explain_instant_save' => 'Perubahan di sini disimpan secara instan.',
'attachments_items' => 'Item Terlampir',
- 'attachments_upload' => 'Unggah File',
+ 'attachments_upload' => 'Unggah Berkas',
'attachments_link' => 'Lampirkan Tautan',
'attachments_set_link' => 'Setel Tautan',
'attachments_delete' => 'Anda yakin ingin menghapus lampiran ini?',
'attachments_dropzone' => 'Jatuhkan file atau klik di sini untuk melampirkan file',
- 'attachments_no_files' => 'Tidak ada file yang telah diunggah',
- 'attachments_explain_link' => 'Anda dapat melampirkan link jika Anda memilih untuk tidak mengupload file. Ini bisa berupa tautan ke halaman lain atau tautan ke file di cloud.',
+ 'attachments_no_files' => 'Tidak ada berkas yang telah diunggah',
+ 'attachments_explain_link' => 'Anda dapat melampirkan sebuah tautan jika Anda memilih untuk tidak mengunggah berkas. Ini bisa berupa sebuah tautan ke halaman lain atau tautan ke sebuah berkas di cloud.',
'attachments_link_name' => 'Nama Tautan',
'attachment_link' => 'Lampiran Tautan',
'attachments_link_url' => 'Tautan ke file',
- 'attachments_link_url_hint' => 'Url situs atau file',
+ 'attachments_link_url_hint' => 'Alamat url situs atau berkas',
'attach' => 'Melampirkan',
'attachments_insert_link' => 'Tambahkan Tautan Lampiran ke Halaman',
'attachments_edit_file' => 'Edit File',
'attachments_edit_file_name' => 'Nama file',
- 'attachments_edit_drop_upload' => 'Lepaskan file atau klik di sini untuk mengupload dan menimpa',
+ 'attachments_edit_drop_upload' => 'Jatuhkan berkas atau klik di sini untuk mengunggah dan menimpa',
'attachments_order_updated' => 'Urutan lampiran diperbarui',
'attachments_updated_success' => 'Detail lampiran diperbarui',
'attachments_deleted' => 'Lampiran dihapus',
- 'attachments_file_uploaded' => 'File berhasil diunggah',
+ 'attachments_file_uploaded' => 'Berkas berhasil diunggah',
'attachments_file_updated' => 'File berhasil diperbarui',
'attachments_link_attached' => 'Tautan berhasil dilampirkan ke halaman',
'templates' => 'Template',
'email_confirmation_expired' => 'Token konfirmasi telah kedaluwarsa, Email konfirmasi baru telah dikirim.',
'email_confirmation_awaiting' => 'Alamat email untuk akun yang digunakan perlu dikonfirmasi',
'ldap_fail_anonymous' => 'Akses LDAP gagal menggunakan pengikatan anonim',
- 'ldap_fail_authed' => 'Akses LDAP gagal menggunakan detail dn & sandi yang diberikan',
+ 'ldap_fail_authed' => 'Akses LDAP gagal menggunakan rincian dn & sandi yang diberikan',
'ldap_extension_not_installed' => 'Ekstensi LDAP PHP tidak terpasang',
'ldap_cannot_connect' => 'Tidak dapat terhubung ke server ldap, Koneksi awal gagal',
'saml_already_logged_in' => 'Telah masuk',
'saml_user_not_registered' => 'Pengguna :name tidak terdaftar dan pendaftaran otomatis dinonaktifkan',
- 'saml_no_email_address' => 'Tidak dapat menemukan alamat email untuk pengguna ini dalam data yang diberikan oleh sistem autentikasi eksternal',
- 'saml_invalid_response_id' => 'Permintaan dari sistem otentikasi eksternal tidak dikenali oleh proses yang dimulai oleh aplikasi ini. Menavigasi kembali setelah masuk dapat menyebabkan masalah ini.',
- 'saml_fail_authed' => 'Login menggunakan :system gagal, sistem tidak memberikan otorisasi yang berhasil',
+ 'saml_no_email_address' => 'Tidak dapat menemukan sebuah alamat email untuk pengguna ini, dalam data yang diberikan oleh sistem autentikasi eksternal',
+ 'saml_invalid_response_id' => 'Permintaan dari sistem otentikasi eksternal tidak dikenali oleh sebuah proses yang dimulai oleh aplikasi ini. Menavigasi kembali setelah masuk dapat menyebabkan masalah ini.',
+ 'saml_fail_authed' => 'Masuk menggunakan :system gagal, sistem tidak memberikan otorisasi yang berhasil',
'social_no_action_defined' => 'Tidak ada tindakan yang ditentukan',
- 'social_login_bad_response' => "Kesalahan diterima selama :socialAccount :\n:error",
- 'social_account_in_use' => 'Ini:socialAccount sudah digunakan, Coba masuk melalui opsi :socialAccount.',
+ 'social_login_bad_response' => "Kesalahan yang diterima selama masuk menggunakan :socialAccount : \n:error",
+ 'social_account_in_use' => 'Akun :socialAccount ini sudah digunakan, Coba masuk melalui opsi :socialAccount.',
'social_account_email_in_use' => 'Email :email sudah digunakan. Jika Anda sudah memiliki akun, Anda dapat menghubungkan :socialAccount Anda dari pengaturan profil Anda.',
- 'social_account_existing' => 'Akun ini :socialAccount sudah dilampirkan ke profil Anda.',
- 'social_account_already_used_existing' => 'Akun ini :socialAccount sudah digunakan oleh pengguna lain.',
- 'social_account_not_used' => 'Akun :socialAccount tidak ditautkan ke pengguna mana pun. Harap lampirkan di pengaturan profil Anda. ',
+ 'social_account_existing' => 'Akun :socialAccount ini sudah dilampirkan ke profil Anda.',
+ 'social_account_already_used_existing' => 'Akun :socialAccount ini sudah digunakan oleh pengguna lain.',
+ 'social_account_not_used' => 'Akun :socialAccount ini tidak ditautkan ke pengguna mana pun. Harap lampirkan di dalam pengaturan profil Anda. ',
'social_account_register_instructions' => 'Jika Anda belum memiliki akun, Anda dapat mendaftarkan akun menggunakan opsi :socialAccount.',
'social_driver_not_found' => 'Pengemudi sosial tidak ditemukan',
'social_driver_not_configured' => 'Pengaturan sosial :socialAccount Anda tidak dikonfigurasi dengan benar.',
'invite_token_expired' => 'Tautan undangan ini telah kedaluwarsa. Sebagai gantinya, Anda dapat mencoba mengatur ulang kata sandi akun Anda.',
// System
- 'path_not_writable' => 'Jalur file :filePath tidak dapat diunggah ke. Pastikan itu dapat ditulis ke server.',
- 'cannot_get_image_from_url' => 'Tidak bisa mendapatkan gambar dari :url',
+ 'path_not_writable' => 'Jalur berkas :filePath tidak dapat diunggah. Pastikan berkas tersebut dapat ditulis ke server.',
+ 'cannot_get_image_from_url' => 'Tidak dapat mengambil gambar dari :url',
'cannot_create_thumbs' => 'Server tidak dapat membuat thumbnail. Harap periksa apakah Anda telah memasang ekstensi GD PHP.',
- 'server_upload_limit' => 'Server tidak mengizinkan unggahan dengan ukuran ini. Harap coba ukuran file yang lebih kecil.',
- 'uploaded' => 'Server tidak mengizinkan unggahan dengan ukuran ini. Harap coba ukuran file yang lebih kecil.',
- 'image_upload_error' => 'Terjadi kesalahan saat mengupload gambar',
+ 'server_upload_limit' => 'Server tidak mengizinkan unggahan dengan ukuran ini. Harap coba ukuran berkas yang lebih kecil.',
+ 'uploaded' => 'Server tidak mengizinkan unggahan dengan ukuran ini. Harap coba ukuran berkas yang lebih kecil.',
+ 'image_upload_error' => 'Terjadi kesalahan saat mengunggah gambar',
'image_upload_type_error' => 'Jenis gambar yang diunggah tidak valid',
- 'file_upload_timeout' => 'Waktu unggah file telah habis.',
+ 'file_upload_timeout' => 'Unggahan berkas telah habis waktu.',
// Attachments
'attachment_not_found' => 'Lampiran tidak ditemukan',
// Pages
'page_draft_autosave_fail' => 'Gagal menyimpan draf. Pastikan Anda memiliki koneksi internet sebelum menyimpan halaman ini',
- 'page_custom_home_deletion' => 'Tidak dapat menghapus halaman saat disetel sebagai beranda',
+ 'page_custom_home_deletion' => 'Tidak dapat menghapus sebuah halaman saat diatur sebagai sebuah halaman beranda',
// Entities
'entity_not_found' => 'Entitas tidak ditemukan',
'users_cannot_delete_guest' => 'Anda tidak dapat menghapus pengguna tamu',
// Roles
- 'role_cannot_be_edited' => 'Peran ini tidak dapat diedit',
+ 'role_cannot_be_edited' => 'Peran ini tidak dapat disunting',
'role_system_cannot_be_deleted' => 'Peran ini adalah peran sistem dan tidak dapat dihapus',
'role_registration_default_cannot_delete' => 'Peran ini tidak dapat dihapus jika disetel sebagai peran pendaftaran default',
'role_cannot_remove_only_admin' => 'Pengguna ini adalah satu-satunya pengguna yang ditetapkan ke peran administrator. Tetapkan peran administrator untuk pengguna lain sebelum mencoba untuk menghapusnya di sini.',
'404_page_not_found' => 'Halaman tidak ditemukan',
'sorry_page_not_found' => 'Maaf, Halaman yang Anda cari tidak dapat ditemukan.',
'sorry_page_not_found_permission_warning' => 'Jika Anda mengharapkan halaman ini ada, Anda mungkin tidak memiliki izin untuk melihatnya.',
+ 'image_not_found' => 'Gambar tidak ditemukan',
+ 'image_not_found_subtitle' => 'Maaf, Berkas gambar yang Anda cari tidak dapat ditemukan.',
+ 'image_not_found_details' => 'Jika Anda mengharapkan gambar ini ada, gambar itu mungkin telah dihapus.',
'return_home' => 'Kembali ke home',
'error_occurred' => 'Terjadi kesalahan',
'app_down' => ':appName sedang down sekarang',
'user_api_token_update_success' => 'Token API berhasil diperbarui',
'user_api_token' => 'Token API',
'user_api_token_id' => 'Token ID',
- 'user_api_token_id_desc' => 'Ini adalah pengenal yang dibuat oleh sistem yang tidak dapat diedit untuk token ini yang perlu disediakan dalam permintaan API.',
+ 'user_api_token_id_desc' => 'Ini adalah sebuah pengenal yang dihasilkan oleh sistem yang tidak dapat disunting untuk token ini yang perlu untuk disediakan dalam permintaan API.',
'user_api_token_secret' => 'Token Secret',
'user_api_token_secret_desc' => 'Ini adalah rahasia yang dihasilkan sistem untuk token ini yang perlu disediakan dalam permintaan API. Ini hanya akan ditampilkan kali ini jadi salin nilai ini ke tempat yang aman dan terlindungi.',
'user_api_token_created' => 'Token dibuat :timeAgo',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'timezone' => ':attribute harus menjadi zona yang valid.',
'unique' => ':attribute sudah diambil.',
'url' => ':attribute format tidak valid.',
- 'uploaded' => 'File tidak dapat diunggah. Server mungkin tidak menerima file dengan ukuran ini.',
+ 'uploaded' => 'Berkas tidak dapat diunggah. Server mungkin tidak menerima berkas dengan ukuran ini.',
// Custom validation lines
'custom' => [
return [
// Pages
- 'page_create' => 'ha creato la pagina',
+ 'page_create' => 'pagina creata',
'page_create_notification' => 'Pagina Creata Correttamente',
'page_update' => 'ha aggiornato la pagina',
'page_update_notification' => 'Pagina Aggiornata Correttamente',
'bookshelf_delete' => 'ha eliminato la libreria',
'bookshelf_delete_notification' => 'Libreria Eliminata Correttamente',
+ // Favourites
+ 'favourite_add_notification' => '":name" è stato aggiunto ai tuoi preferiti',
+ 'favourite_remove_notification' => '":name" è stato rimosso dai tuoi preferiti',
+
// Other
'commented_on' => 'ha commentato in',
- 'permissions_update' => 'updated permissions',
+ 'permissions_update' => 'autorizzazioni aggiornate',
];
'description' => 'Descrizione',
'role' => 'Ruolo',
'cover_image' => 'Immagine di copertina',
- 'cover_image_description' => 'Questa immagine dovrebbe essere approssimatamente 440x250px.',
+ 'cover_image_description' => 'Questa immagine dovrebbe essere approssimativamente 440x250px.',
// Actions
'actions' => 'Azioni',
'copy' => 'Copia',
'reply' => 'Rispondi',
'delete' => 'Elimina',
- 'delete_confirm' => 'Confirm Deletion',
+ 'delete_confirm' => 'Conferma Eliminazione',
'search' => 'Cerca',
'search_clear' => 'Pulisci Ricerca',
'reset' => 'Azzera',
'remove' => 'Rimuovi',
'add' => 'Aggiungi',
'fullscreen' => 'Schermo intero',
+ 'favourite' => 'Aggiungi ai Preferiti',
+ 'unfavourite' => 'Rimuovi dai preferiti',
+ 'next' => 'Successivo',
+ 'previous' => 'Precedente',
// Sort Options
'sort_options' => 'Opzioni Ordinamento',
'sort_ascending' => 'Ordine Ascendente',
'sort_descending' => 'Ordine Discendente',
'sort_name' => 'Nome',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Predefinito',
'sort_created_at' => 'Data Creazione',
'sort_updated_at' => 'Data Aggiornamento',
'breadcrumb' => 'Navigazione',
// Header
- 'profile_menu' => 'Menu del profilo',
+ 'header_menu_expand' => 'Espandi Menù Intestazione',
+ 'profile_menu' => 'Menù del profilo',
'view_profile' => 'Visualizza Profilo',
'edit_profile' => 'Modifica Profilo',
'dark_mode' => 'Modalità Scura',
// Layout tabs
'tab_info' => 'Info',
+ 'tab_info_label' => 'Tab: Mostra Informazioni Secondarie',
'tab_content' => 'Contenuto',
+ 'tab_content_label' => 'Tab: Mostra Contenuto Principale',
// Email Content
'email_action_help' => 'Se hai problemi nel cliccare il pulsante ":actionText", copia e incolla lo URL sotto nel tuo browser:',
// Footer Link Options
// Not directly used but available for convenience to users.
- 'privacy_policy' => 'Privacy Policy',
- 'terms_of_service' => 'Terms of Service',
+ 'privacy_policy' => 'Norme sulla privacy',
+ 'terms_of_service' => 'Condizioni del Servizio',
];
'image_load_more' => 'Carica Altre',
'image_image_name' => 'Nome Immagine',
'image_delete_used' => 'Questa immagine è usata nelle pagine elencate.',
- 'image_delete_confirm_text' => 'Are you sure you want to delete this image?',
+ 'image_delete_confirm_text' => 'Sei sicuro di voler eliminare questa immagine?',
'image_select_image' => 'Seleziona Immagine',
'image_dropzone' => 'Rilascia immagini o clicca qui per caricarle',
'images_deleted' => 'Immagini Eliminate',
'meta_created_name' => 'Creato :timeLength da :user',
'meta_updated' => 'Aggiornato :timeLength',
'meta_updated_name' => 'Aggiornato :timeLength da :user',
- 'meta_owned_name' => 'Owned by :user',
+ 'meta_owned_name' => 'Creati da :user',
'entity_select' => 'Selezione Entità',
'images' => 'Immagini',
'my_recent_drafts' => 'Bozze Recenti',
'my_recently_viewed' => 'Visti di recente',
+ 'my_most_viewed_favourites' => 'I Miei Preferiti Più Visti',
+ 'my_favourites' => 'I miei Preferiti',
'no_pages_viewed' => 'Non hai visto nessuna pagina',
'no_pages_recently_created' => 'Nessuna pagina è stata creata di recente',
'no_pages_recently_updated' => 'Nessuna pagina è stata aggiornata di recente',
'permissions_intro' => 'Una volta abilitati, questi permessi avranno la priorità su tutti gli altri.',
'permissions_enable' => 'Abilita Permessi Custom',
'permissions_save' => 'Salva Permessi',
- 'permissions_owner' => 'Owner',
+ 'permissions_owner' => 'Proprietario',
// Search
'search_results' => 'Risultati Ricerca',
'search_permissions_set' => 'Permessi impostati',
'search_created_by_me' => 'Creati da me',
'search_updated_by_me' => 'Aggiornati da me',
- 'search_owned_by_me' => 'Owned by me',
+ 'search_owned_by_me' => 'Creati da me',
'search_date_options' => 'Opzioni Data',
'search_updated_before' => 'Aggiornati prima del',
'search_updated_after' => 'Aggiornati dopo il',
'chapters_create' => 'Crea un nuovo capitolo',
'chapters_delete' => 'Elimina Capitolo',
'chapters_delete_named' => 'Elimina il capitolo :chapterName',
- 'chapters_delete_explain' => 'This will delete the chapter with the name \':chapterName\'. All pages that exist within this chapter will also be deleted.',
+ 'chapters_delete_explain' => 'Procedendo si eliminerà il capitolo denominato \':chapterName\'. Anche le pagine in esso contenute saranno eliminate.',
'chapters_delete_confirm' => 'Sei sicuro di voler eliminare questo capitolo?',
'chapters_edit' => 'Elimina Capitolo',
'chapters_edit_named' => 'Modifica il capitolo :chapterName',
'pages_revisions' => 'Versioni Pagina',
'pages_revisions_named' => 'Versioni della pagina :pageName',
'pages_revision_named' => 'Versione della pagina :pageName',
- 'pages_revision_restored_from' => 'Restored from #:id; :summary',
+ 'pages_revision_restored_from' => 'Ripristinato da #:id; :summary',
'pages_revisions_created_by' => 'Creata Da',
'pages_revisions_date' => 'Data Versione',
'pages_revisions_number' => '#',
'attachments_link_url' => 'Link al file',
'attachments_link_url_hint' => 'Url del sito o del file',
'attach' => 'Allega',
- 'attachments_insert_link' => 'Add Attachment Link to Page',
+ 'attachments_insert_link' => 'Aggiungi Link Allegato alla Pagina',
'attachments_edit_file' => 'Modifica File',
'attachments_edit_file_name' => 'Nome File',
'attachments_edit_drop_upload' => 'Rilascia file o clicca qui per caricare e sovrascrivere',
'404_page_not_found' => 'Pagina Non Trovata',
'sorry_page_not_found' => 'La pagina che stavi cercando non è stata trovata.',
'sorry_page_not_found_permission_warning' => 'Se pensi che questa pagina possa esistere, potresti non avere i permessi per visualizzarla.',
+ 'image_not_found' => 'Immagine non trovata',
+ 'image_not_found_subtitle' => 'Spiacente, l\'immagine che stai cercando non è stata trovata.',
+ 'image_not_found_details' => 'Se ti aspettavi che questa immagine esistesse, potrebbe essere stata cancellata.',
'return_home' => 'Ritorna alla home',
'error_occurred' => 'C\'è Stato un errore',
'app_down' => ':appName è offline',
'back_soon' => 'Ritornerà presto.',
// API errors
- 'api_no_authorization_found' => 'No authorization token found on the request',
+ 'api_no_authorization_found' => 'Nessun token di autorizzazione trovato nella richiesta',
'api_bad_authorization_format' => 'Un token di autorizzazione è stato trovato nella richiesta, ma il formato sembra non corretto',
- 'api_user_token_not_found' => 'No matching API token was found for the provided authorization token',
- 'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect',
+ 'api_user_token_not_found' => 'Nessun token API valido è stato trovato nel token di autorizzazione fornito',
+ 'api_incorrect_token_secret' => 'Il token segreto fornito per il token API utilizzato non è corretto',
'api_user_no_api_permission' => 'Il proprietario del token API utilizzato non ha il permesso di effettuare chiamate API',
- 'api_user_token_expired' => 'The authorization token used has expired',
+ 'api_user_token_expired' => 'Il token di autorizzazione utilizzato è scaduto',
// Settings & Maintenance
- 'maintenance_test_email_failure' => 'Error thrown when sending a test email:',
+ 'maintenance_test_email_failure' => 'Si è verificato un errore durante l\'invio di una e-mail di prova:',
];
'password' => 'La password deve avere almeno sei caratteri e corrispondere alla conferma.',
'user' => "Non possiamo trovare un utente per quella mail.",
- 'token' => 'The password reset token is invalid for this email address.',
+ 'token' => 'Il token per reimpostare la password non è valido per questo indirizzo email.',
'sent' => 'Ti abbiamo inviato via mail il link per reimpostare la password!',
- 'reset' => 'La tua password è stata resettata!',
+ 'reset' => 'La tua password è stata reimpostata!',
];
'app_homepage' => 'Homepage Applicazione',
'app_homepage_desc' => 'Seleziona una pagina da mostrare nella home anzichè quella di default. I permessi della pagina sono ignorati per quella selezionata.',
'app_homepage_select' => 'Seleziona una pagina',
- 'app_footer_links' => 'Footer Links',
- 'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
- 'app_footer_links_label' => 'Link Label',
- 'app_footer_links_url' => 'Link URL',
- 'app_footer_links_add' => 'Add Footer Link',
+ 'app_footer_links' => 'Link in basso',
+ 'app_footer_links_desc' => 'Aggiungi link da mostrare in basso nel sito. Questi saranno visibili in fondo alla maggior parte delle pagine, incluse quelle che non richiedono un autenticazione. Puoi usare l\'etichetta "trans::<chiave>" per utilizzare le traduzioni implementate nella piattaforma. Esempio: usando "trans::common.privacy_policy" mostrerà il testo tradotto "Norme sulla privacy" e "trans::common.terms_of_service" mostrerà il testo tradotto "Condizioni del Servizio".',
+ 'app_footer_links_label' => 'Etichetta del Link',
+ 'app_footer_links_url' => 'URL del Link',
+ 'app_footer_links_add' => 'Aggiungi Link in basso',
'app_disable_comments' => 'Disattiva commenti',
'app_disable_comments_toggle' => 'Disabilita commenti',
'app_disable_comments_desc' => 'Disabilita i commenti su tutte le pagine nell\'applicazione. I commenti esistenti non sono mostrati. ',
// Color settings
'content_colors' => 'Colori del contenuto',
'content_colors_desc' => 'Imposta i colori per tutti gli elementi nella gerarchia della pagina. È raccomandato scegliere colori con una luminosità simile a quelli di default per una maggiore leggibilità.',
- 'bookshelf_color' => 'Colore delle libreria',
+ 'bookshelf_color' => 'Colore della libreria',
'book_color' => 'Colore del libro',
'chapter_color' => 'Colore del capitolo',
'page_color' => 'Colore della Pagina',
'reg_enable_toggle' => 'Abilita registrazione',
'reg_enable_desc' => 'Quando la registrazione è abilitata, l\utente sarà in grado di registrarsi all\'applicazione. Al momento della registrazione gli verrà associato un ruolo utente predefinito.',
'reg_default_role' => 'Ruolo predefinito dopo la registrazione',
- 'reg_enable_external_warning' => 'The option above is ignored while external LDAP or SAML authentication is active. User accounts for non-existing members will be auto-created if authentication, against the external system in use, is successful.',
+ 'reg_enable_external_warning' => 'L\'opzione precedente viene ignorata se l\'autenticazione esterna tramite LDAP o SAML è attiva. Se l\'autenticazione (effettuata sul sistema esterno) sarà valida, gli account di eventuali membri non registrati saranno creati in automatico.',
'reg_email_confirmation' => 'Conferma Email',
'reg_email_confirmation_toggle' => 'Richiedi conferma email',
'reg_confirm_email_desc' => 'Se la restrizione per dominio è usata la conferma della mail sarà richiesta e la scelta ignorata.',
'maint' => 'Manutenzione',
'maint_image_cleanup' => 'Pulizia Immagini',
'maint_image_cleanup_desc' => "Esegue la scansione del contenuto delle pagine e delle revisioni per verificare quali immagini e disegni sono attualmente in uso e quali immagini sono ridondanti. Assicurati di creare backup completo del database e delle immagini prima di eseguire la pulizia.",
- 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
+ 'maint_delete_images_only_in_revisions' => 'Elimina anche le immagini che esistono solo nelle vecchie revisioni della pagina',
'maint_image_cleanup_run' => 'Esegui Pulizia',
'maint_image_cleanup_warning' => ':count immagini potenzialmente inutilizzate sono state trovate. Sei sicuro di voler eliminare queste immagini?',
'maint_image_cleanup_success' => ':count immagini potenzialmente inutilizzate trovate e eliminate!',
'maint_send_test_email_mail_subject' => 'Email di Test',
'maint_send_test_email_mail_greeting' => 'L\'invio delle email sembra funzionare!',
'maint_send_test_email_mail_text' => 'Congratulazioni! Siccome hai ricevuto questa notifica email, le tue impostazioni sembrano essere configurate correttamente.',
- 'maint_recycle_bin_desc' => 'Deleted shelves, books, chapters & pages are sent to the recycle bin so they can be restored or permanently deleted. Older items in the recycle bin may be automatically removed after a while depending on system configuration.',
+ 'maint_recycle_bin_desc' => 'Le librerie, i libri, i capitoli e le pagine cancellati vengono inviati al cestino in modo che possano essere ripristinati o eliminati definitivamente. Gli elementi più vecchi nel cestino possono essere automaticamente rimossi dopo un certo periodo, a seconda della configurazione del sistema.',
'maint_recycle_bin_open' => 'Apri il Cestino',
// Recycle Bin
'recycle_bin' => 'Cestino',
- 'recycle_bin_desc' => 'Here you can restore items that have been deleted or choose to permanently remove them from the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
- 'recycle_bin_deleted_item' => 'Deleted Item',
+ 'recycle_bin_desc' => 'Qui è possibile ripristinare gli elementi che sono stati eliminati o scegliere di rimuoverli definitivamente dal sistema. Questo elenco non è filtrato a differenza di elenchi di attività simili nel sistema in cui vengono applicati i filtri autorizzazioni.',
+ 'recycle_bin_deleted_item' => 'Elimina Elemento',
'recycle_bin_deleted_by' => 'Cancellato da',
'recycle_bin_deleted_at' => 'Orario Cancellazione',
'recycle_bin_permanently_delete' => 'Elimina Definitivamente',
'recycle_bin_restore' => 'Ripristina',
- 'recycle_bin_contents_empty' => 'The recycle bin is currently empty',
+ 'recycle_bin_contents_empty' => 'Al momento il cestino è vuoto',
'recycle_bin_empty' => 'Svuota Cestino',
- 'recycle_bin_empty_confirm' => 'This will permanently destroy all items in the recycle bin including content contained within each item. Are you sure you want to empty the recycle bin?',
- 'recycle_bin_destroy_confirm' => 'This action will permanently delete this item, along with any child elements listed below, from the system and you will not be able to restore this content. Are you sure you want to permanently delete this item?',
- 'recycle_bin_destroy_list' => 'Items to be Destroyed',
- 'recycle_bin_restore_list' => 'Items to be Restored',
- 'recycle_bin_restore_confirm' => 'This action will restore the deleted item, including any child elements, to their original location. If the original location has since been deleted, and is now in the recycle bin, the parent item will also need to be restored.',
- 'recycle_bin_restore_deleted_parent' => 'The parent of this item has also been deleted. These will remain deleted until that parent is also restored.',
- 'recycle_bin_destroy_notification' => 'Deleted :count total items from the recycle bin.',
- 'recycle_bin_restore_notification' => 'Restored :count total items from the recycle bin.',
+ 'recycle_bin_empty_confirm' => 'Questa operazione cancellerà definitivamente tutti gli elementi presenti nel cestino, inclusi i contenuti relativi a ciascun elemento. Sei sicuro di voler svuotare il cestino?',
+ 'recycle_bin_destroy_confirm' => 'Questa operazione eliminerà permanentemente questo elemento (insieme a tutti i relativi elementi elencati qui sotto) dal sistema e non sarà più possibile recuperarlo. Sei sicuro di voler eliminare permanentemente questo elemento?',
+ 'recycle_bin_destroy_list' => 'Elementi da Eliminare definitivamente',
+ 'recycle_bin_restore_list' => 'Elementi da Ripristinare',
+ 'recycle_bin_restore_confirm' => 'Questa azione ripristinerà l\'elemento eliminato, compresi gli elementi figli, nella loro posizione originale. Se la posizione originale è stata eliminata, ed è ora nel cestino, anche l\'elemento padre dovrà essere ripristinato.',
+ 'recycle_bin_restore_deleted_parent' => 'L\'elemento padre di questo elemento è stato eliminato. Questo elemento rimarrà eliminato fino a che l\'elemento padre non sarà ripristinato.',
+ 'recycle_bin_destroy_notification' => 'Eliminati :count elementi dal cestino.',
+ 'recycle_bin_restore_notification' => 'Ripristinati :count elementi dal cestino.',
// Audit Log
- 'audit' => 'Audit Log',
- 'audit_desc' => 'This audit log displays a list of activities tracked in the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
- 'audit_event_filter' => 'Event Filter',
- 'audit_event_filter_no_filter' => 'No Filter',
- 'audit_deleted_item' => 'Deleted Item',
- 'audit_deleted_item_name' => 'Name: :name',
+ 'audit' => 'Registro di Controllo',
+ 'audit_desc' => 'Questo registro di controllo mostra la lista delle attività registrate dal sistema. Questa lista, a differenza di altre liste del sistema a cui vengono applicate dei filtri, è integrale.',
+ 'audit_event_filter' => 'Filtra Eventi',
+ 'audit_event_filter_no_filter' => 'Nessun Filtro',
+ 'audit_deleted_item' => 'Elimina Elemento',
+ 'audit_deleted_item_name' => 'Nome: :name',
'audit_table_user' => 'Utente',
'audit_table_event' => 'Evento',
- 'audit_table_related' => 'Related Item or Detail',
- 'audit_table_date' => 'Activity Date',
- 'audit_date_from' => 'Date Range From',
- 'audit_date_to' => 'Date Range To',
+ 'audit_table_related' => 'Elemento o Dettaglio correlato',
+ 'audit_table_date' => 'Data attività',
+ 'audit_date_from' => 'Dalla data',
+ 'audit_date_to' => 'Alla data',
// Role Settings
'roles' => 'Ruoli',
'role_manage_entity_permissions' => 'Gestire tutti i permessi di libri, capitoli e pagine',
'role_manage_own_entity_permissions' => 'Gestire i permessi sui propri libri, capitoli e pagine',
'role_manage_page_templates' => 'Gestisci template pagine',
- 'role_access_api' => 'Access system API',
+ 'role_access_api' => 'API sistema d\'accesso',
'role_manage_settings' => 'Gestire impostazioni app',
'role_asset' => 'Permessi Entità',
- 'roles_system_warning' => 'Be aware that access to any of the above three permissions can allow a user to alter their own privileges or the privileges of others in the system. Only assign roles with these permissions to trusted users.',
+ 'roles_system_warning' => 'Siate consapevoli che l\'accesso a uno dei tre permessi qui sopra, può consentire a un utente di modificare i propri privilegi o i privilegi di altri nel sistema. Assegna ruoli con questi permessi solo ad utenti fidati.',
'role_asset_desc' => 'Questi permessi controllano l\'accesso di default alle entità. I permessi nei Libri, Capitoli e Pagine sovrascriveranno questi.',
'role_asset_admins' => 'Gli amministratori hanno automaticamente accesso a tutti i contenuti ma queste opzioni possono mostrare o nascondere le opzioni della UI.',
'role_all' => 'Tutti',
'user_profile' => 'Profilo Utente',
'users_add_new' => 'Aggiungi Nuovo Utente',
'users_search' => 'Cerca Utenti',
- 'users_latest_activity' => 'Latest Activity',
+ 'users_latest_activity' => 'Ultima Attività',
'users_details' => 'Dettagli Utente',
'users_details_desc' => 'Imposta un nome e un indirizzo email per questo utente. L\'indirizzo email verrà utilizzato per accedere all\'applicazione.',
'users_details_desc_no_email' => 'Imposta un nome per questo utente così gli altri possono riconoscerlo.',
'users_delete_named' => 'Elimina l\'utente :userName',
'users_delete_warning' => 'Questo eliminerà completamente l\'utente \':userName\' dal sistema.',
'users_delete_confirm' => 'Sei sicuro di voler eliminare questo utente?',
- 'users_migrate_ownership' => 'Migrate Ownership',
- 'users_migrate_ownership_desc' => 'Select a user here if you want another user to become the owner of all items currently owned by this user.',
+ 'users_migrate_ownership' => 'Cambia Proprietario',
+ 'users_migrate_ownership_desc' => 'Seleziona qui un utente se vuoi che un altro utente diventi il proprietario di tutti gli elementi attualmente di proprietà di questo utente.',
'users_none_selected' => 'Nessun utente selezionato',
'users_delete_success' => 'Utente rimosso con successo',
'users_edit' => 'Modifica Utente',
'users_social_disconnect' => 'Disconnetti Account',
'users_social_connected' => 'L\'account :socialAccount è stato connesso correttamente al tuo profilo.',
'users_social_disconnected' => 'L\'account :socialAccount è stato disconnesso correttamente dal tuo profilo.',
- 'users_api_tokens' => 'API Tokens',
+ 'users_api_tokens' => 'Token API',
'users_api_tokens_none' => 'No API tokens have been created for this user',
'users_api_tokens_create' => 'Crea Token',
'users_api_tokens_expires' => 'Scade',
- 'users_api_tokens_docs' => 'API Documentation',
+ 'users_api_tokens_docs' => 'Documentazione API',
// API Tokens
'user_api_token_create' => 'Crea Token API',
'user_api_token_expiry' => 'Data di scadenza',
'user_api_token_expiry_desc' => 'Set a date at which this token expires. After this date, requests made using this token will no longer work. Leaving this field blank will set an expiry 100 years into the future.',
'user_api_token_create_secret_message' => 'Immediately after creating this token a "Token ID" & "Token Secret" will be generated and displayed. The secret will only be shown a single time so be sure to copy the value to somewhere safe and secure before proceeding.',
- 'user_api_token_create_success' => 'API token successfully created',
- 'user_api_token_update_success' => 'API token successfully updated',
+ 'user_api_token_create_success' => 'Token API creato correttamente',
+ 'user_api_token_update_success' => 'Token API aggiornato correttamente',
'user_api_token' => 'Token API',
'user_api_token_id' => 'Token ID',
'user_api_token_id_desc' => 'This is a non-editable system generated identifier for this token which will need to be provided in API requests.',
- 'user_api_token_secret' => 'Token Secret',
+ 'user_api_token_secret' => 'Token Segreto',
'user_api_token_secret_desc' => 'This is a system generated secret for this token which will need to be provided in API requests. This will only be displayed this one time so copy this value to somewhere safe and secure.',
'user_api_token_created' => 'Token Aggiornato :timeAgo',
'user_api_token_updated' => 'Token Aggiornato :timeAgo',
'user_api_token_delete' => 'Elimina Token',
- 'user_api_token_delete_warning' => 'This will fully delete this API token with the name \':tokenName\' from the system.',
+ 'user_api_token_delete_warning' => 'Questa operazione eliminerà irreversibilmente dal sistema il token API denominato \':tokenName\'.',
'user_api_token_delete_confirm' => 'Sei sicuri di voler eliminare questo token API?',
'user_api_token_delete_success' => 'Token API eliminato correttamente',
'ar' => 'العربية',
'bg' => 'Bǎlgarski',
'bs' => 'Bosanski',
- 'ca' => 'Català',
+ 'ca' => 'Catalano',
'cs' => 'Česky',
'da' => 'Danese',
'de' => 'Deutsch (Sie)',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'required_without' => 'Il campo :attribute è richiesto quando :values non è presente.',
'required_without_all' => 'Il campo :attribute è richiesto quando nessuno dei :values sono presenti.',
'same' => ':attribute e :other devono corrispondere.',
- 'safe_url' => 'The provided link may not be safe.',
+ 'safe_url' => 'Il link inserito potrebbe non essere sicuro.',
'size' => [
'numeric' => 'Il campo :attribute deve essere :size.',
'file' => 'Il campo :attribute deve essere :size kilobytes.',
'bookshelf_delete' => 'ブックが削除されました。',
'bookshelf_delete_notification' => '本棚を削除しました',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'コメントする',
'permissions_update' => 'updated permissions',
'remove' => '削除',
'add' => '追加',
'fullscreen' => 'Fullscreen',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Sort Options',
'breadcrumb' => 'Breadcrumb',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Profile Menu',
'view_profile' => 'プロフィール表示',
'edit_profile' => 'プロフィール編集',
// Layout tabs
'tab_info' => 'Info',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Content',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => '":actionText" をクリックできない場合、以下のURLをコピーしブラウザで開いてください:',
'images' => '画像',
'my_recent_drafts' => '最近の下書き',
'my_recently_viewed' => '閲覧履歴',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'なにもページを閲覧していません',
'no_pages_recently_created' => '最近作成されたページはありません',
'no_pages_recently_updated' => '最近更新されたページはありません。',
'404_page_not_found' => 'ページが見つかりません',
'sorry_page_not_found' => 'ページを見つけることができませんでした。',
'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'ホームに戻る',
'error_occurred' => 'エラーが発生しました',
'app_down' => ':appNameは現在停止しています',
'settings_save_success' => '設定を保存しました',
// App Settings
- 'app_customization' => 'Customization',
- 'app_features_security' => 'Features & Security',
+ 'app_customization' => 'カスタマイズ',
+ 'app_features_security' => '機能とセキュリティ',
'app_name' => 'アプリケーション名',
'app_name_desc' => 'この名前はヘッダーやEメール内で表示されます。',
'app_name_header' => 'ヘッダーにアプリケーション名を表示する',
'app_public_access' => 'パブリック・アクセス',
- 'app_public_access_desc' => 'Enabling this option will allow visitors, that are not logged-in, to access content in your BookStack instance.',
- 'app_public_access_desc_guest' => 'Access for public visitors can be controlled through the "Guest" user.',
- 'app_public_access_toggle' => 'Allow public access',
+ 'app_public_access_desc' => 'このオプションを有効にすると、ログインしていない訪問者があなたのBookStackインスタンスのコンテンツにアクセスできるようになります。',
+ 'app_public_access_desc_guest' => '一般の訪問者のアクセスは、「ゲスト」ユーザー権限を通じて制御することができます。',
+ 'app_public_access_toggle' => 'パブリックアクセスを許可',
'app_public_viewing' => 'アプリケーションを公開する',
'app_secure_images' => '画像アップロード時のセキュリティを強化',
- 'app_secure_images_toggle' => 'Enable higher security image uploads',
+ 'app_secure_images_toggle' => 'より高いセキュリティの画像アップロードを可能にする',
'app_secure_images_desc' => 'パフォーマンスの観点から、全ての画像が公開になっています。このオプションを有効にすると、画像URLの先頭にランダムで推測困難な文字列が追加され、アクセスを困難にします。',
'app_editor' => 'ページエディタ',
'app_editor_desc' => 'ここで選択されたエディタを全ユーザが使用します。',
'app_homepage' => 'Application Homepage',
'app_homepage_desc' => 'Select a view to show on the homepage instead of the default view. Page permissions are ignored for selected pages.',
'app_homepage_select' => 'ページを選択',
- 'app_footer_links' => 'Footer Links',
+ 'app_footer_links' => 'フッタのリンク',
'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
- 'app_footer_links_label' => 'Link Label',
- 'app_footer_links_url' => 'Link URL',
+ 'app_footer_links_label' => '表示するテキスト',
+ 'app_footer_links_url' => 'リンク先の URL',
'app_footer_links_add' => 'Add Footer Link',
'app_disable_comments' => 'コメントを無効にする',
'app_disable_comments_toggle' => 'コメントを無効にする',
// Color settings
'content_colors' => 'コンテンツの色',
- 'content_colors_desc' => 'Sets colors for all elements in the page organisation hierarchy. Choosing colors with a similar brightness to the default colors is recommended for readability.',
+ 'content_colors_desc' => 'ページ構成階層のすべての要素に色を設定します。読みやすさを考慮して、デフォルトの色と同じような明るさの色を選ぶことをお勧めします。',
'bookshelf_color' => 'Shelf Color',
'book_color' => 'Book Color',
'chapter_color' => 'Chapter Color',
// Registration Settings
'reg_settings' => '登録設定',
- 'reg_enable' => 'Enable Registration',
- 'reg_enable_toggle' => 'Enable registration',
+ 'reg_enable' => '登録を有効にする',
+ 'reg_enable_toggle' => '登録を有効にする',
'reg_enable_desc' => 'When registration is enabled user will be able to sign themselves up as an application user. Upon registration they are given a single, default user role.',
'reg_default_role' => '新規登録時のデフォルト役割',
- 'reg_enable_external_warning' => 'The option above is ignored while external LDAP or SAML authentication is active. User accounts for non-existing members will be auto-created if authentication, against the external system in use, is successful.',
- 'reg_email_confirmation' => 'Email Confirmation',
- 'reg_email_confirmation_toggle' => 'Require email confirmation',
+ 'reg_enable_external_warning' => '外部のLDAPまたはSAML認証が有効の場合、上記のオプションは無視されます。存在しないメンバーのユーザーアカウントは、使用している外部システムでの認証に成功した場合に自動的に作成されます。',
+ 'reg_email_confirmation' => '確認メール',
+ 'reg_email_confirmation_toggle' => 'メールによる確認を行う',
'reg_confirm_email_desc' => 'ドメイン制限を有効にしている場合はEメール認証が必須となり、この項目は無視されます。',
'reg_confirm_restrict_domain' => 'ドメイン制限',
'reg_confirm_restrict_domain_desc' => '特定のドメインのみ登録できるようにする場合、以下にカンマ区切りで入力します。設定された場合、Eメール認証が必須になります。<br>登録後、ユーザは自由にEメールアドレスを変更できます。',
// Maintenance settings
'maint' => 'メンテナンス',
'maint_image_cleanup' => 'Cleanup Images',
- 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.",
- 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
+ 'maint_image_cleanup_desc' => "ページや履歴の内容をスキャンして、どの画像や図面が現在使用されているか、どの画像が余っているかをチェックします。この機能を実行する前に、データベースと画像の完全なバックアップを作成してください。",
+ 'maint_delete_images_only_in_revisions' => 'また、古いページのリビジョンにしか存在しない画像も削除します。',
'maint_image_cleanup_run' => 'クリーンアップを実行',
- 'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?',
+ 'maint_image_cleanup_warning' => ':count 個、使用されていない可能性のある画像が見つかりました。これらの画像を削除してもよろしいですか?',
'maint_image_cleanup_success' => ':count potentially unused images found and deleted!',
'maint_image_cleanup_nothing_found' => 'No unused images found, Nothing deleted!',
'maint_send_test_email' => 'テストメールを送信',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => '삭제된 서가',
'bookshelf_delete_notification' => '서가 지움',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => '댓글 쓰기',
'permissions_update' => 'updated permissions',
'remove' => '제거',
'add' => '추가',
'fullscreen' => '전체화면',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => '정렬 기준',
'breadcrumb' => '탐색 경로',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => '프로필',
'view_profile' => '프로필 보기',
'edit_profile' => '프로필 바꾸기',
// Layout tabs
'tab_info' => '정보',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => '내용',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => ':actionText를 클릭할 수 없을 때는 웹 브라우저에서 다음 링크로 접속할 수 있습니다.',
'images' => '이미지',
'my_recent_drafts' => '내 최근의 초안 문서',
'my_recently_viewed' => '내가 읽은 문서',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => '문서 없음',
'no_pages_recently_created' => '문서 없음',
'no_pages_recently_updated' => '문서 없음',
'404_page_not_found' => '404 Not Found',
'sorry_page_not_found' => '문서를 못 찾았습니다.',
'sorry_page_not_found_permission_warning' => '이 페이지가 존재하기를 기대했다면, 볼 수 있는 권한이 없을 수 있다.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => '처음으로 돌아가기',
'error_occurred' => '문제가 생겼습니다.',
'app_down' => ':appName에 문제가 있는 것 같습니다',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => '히브리어',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'izdzēsa plauktu',
'bookshelf_delete_notification' => 'Plaukts Veiksmīgi Dzēsts',
+ // Favourites
+ 'favourite_add_notification' => '":name" ir pievienots jūsu favorītiem',
+ 'favourite_remove_notification' => '":name" ir izņemts no jūsu favorītiem',
+
// Other
'commented_on' => 'komentēts',
'permissions_update' => 'atjaunoja atļaujas',
'remove' => 'Noņemt',
'add' => 'Pievienot',
'fullscreen' => 'Pilnekrāns',
+ 'favourite' => 'Pievienot favorītiem',
+ 'unfavourite' => 'Noņemt no favorītiem',
+ 'next' => 'Nākamais',
+ 'previous' => 'Iepriekšējais',
// Sort Options
'sort_options' => 'Kārtošanas Opcijas',
'breadcrumb' => 'Navigācija',
// Header
+ 'header_menu_expand' => 'Izvērst galvenes izvēlni',
'profile_menu' => 'Profila izvēlne',
'view_profile' => 'Apskatīt profilu',
'edit_profile' => 'Rediģēt profilu',
// Layout tabs
'tab_info' => 'Informācija',
+ 'tab_info_label' => 'Tab: Rādīt sekundāro informāciju',
'tab_content' => 'Saturs',
+ 'tab_content_label' => 'Tab: Rādīt galveno saturu',
// Email Content
'email_action_help' => 'Ja ir problēmas noklikšķināt ":actionText" pogu, nokopē un ievieto saiti savā interneta pārlūkā:',
'images' => 'Attēli',
'my_recent_drafts' => 'Mani melnraksti',
'my_recently_viewed' => 'Mani nesen skatītie',
+ 'my_most_viewed_favourites' => 'Mani biežāk skatītie favorīti',
+ 'my_favourites' => 'Mani favorīti',
'no_pages_viewed' => 'Neviena lapa vēl nav skatīta',
'no_pages_recently_created' => 'Nav radīta neviena lapa',
'no_pages_recently_updated' => 'Nav atjaunināta neviena lapa',
'pages_revisions_numbered_changes' => 'Revīzijas #:id izmaiņas',
'pages_revisions_changelog' => 'Izmaiņu žurnāls',
'pages_revisions_changes' => 'Izmaiņas',
- 'pages_revisions_current' => 'Tekošā versija',
+ 'pages_revisions_current' => 'Pašreizējā versija',
'pages_revisions_preview' => 'Priekšskatījums',
'pages_revisions_restore' => 'Atjaunot',
'pages_revisions_none' => 'Šai lapai nav revīziju',
// Revision
'revision_delete_confirm' => 'Vai esat pārliecināts, ka vēlaties dzēst šo revīziju?',
- 'revision_restore_confirm' => 'Vai esat pārliecināts, ka vēlaties atjaunot šo revīziju? Tekošais lapas saturs tiks aizstāts.',
+ 'revision_restore_confirm' => 'Vai tiešām vēlaties atjaunot šo revīziju? Pašreizējais lapas saturs tiks aizvietots.',
'revision_delete_success' => 'Revīzija dzēsta',
- 'revision_cannot_delete_latest' => 'Nevar dzēst tekošo revīziju.'
+ 'revision_cannot_delete_latest' => 'Nevar dzēst pašreizējo revīziju.'
];
'404_page_not_found' => 'Lapa nav atrasta',
'sorry_page_not_found' => 'Atvainojiet, meklētā lapa nav atrasta.',
'sorry_page_not_found_permission_warning' => 'Ja šai lapai būtu bijis te jābūt, jums var nebūt pietiekamas piekļuves tiesības, lai to apskatītu.',
+ 'image_not_found' => 'Attēls nav atrasts',
+ 'image_not_found_subtitle' => 'Atvainojiet, meklētais attēla fails nav atrasts.',
+ 'image_not_found_details' => 'Ja attēlam būtu jābūt pieejamam, iespējams, tas ir ticis izdzēsts.',
'return_home' => 'Atgriezties uz sākumu',
'error_occurred' => 'Radusies kļūda',
'app_down' => ':appName pagaidām nav pieejams',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'slettet bokhylle',
'bookshelf_delete_notification' => 'Bokhyllen ble slettet',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'kommenterte på',
'permissions_update' => 'oppdaterte tilganger',
'remove' => 'Fjern',
'add' => 'Legg til',
'fullscreen' => 'Fullskjerm',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Sorteringsalternativer',
'breadcrumb' => 'Brødsmuler',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Profilmeny',
'view_profile' => 'Vis profil',
'edit_profile' => 'Endre Profile',
// Layout tabs
'tab_info' => 'Informasjon',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Innhold',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Om du har problemer med å trykke på «:actionText»-knappen, bruk nettadressen under for å gå direkte dit:',
'images' => 'Bilder',
'my_recent_drafts' => 'Mine nylige utkast',
'my_recently_viewed' => 'Mine nylige visninger',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Du har ikke sett på noen sider',
'no_pages_recently_created' => 'Ingen sider har nylig blitt opprettet',
'no_pages_recently_updated' => 'Ingen sider har nylig blitt oppdatert',
'404_page_not_found' => 'Siden finnes ikke',
'sorry_page_not_found' => 'Beklager, siden du leter etter ble ikke funnet.',
'sorry_page_not_found_permission_warning' => 'Hvis du forventet at denne siden skulle eksistere, har du kanskje ikke tillatelse til å se den.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Gå til hovedside',
'error_occurred' => 'En feil oppsto',
'app_down' => ':appName er nede for øyeblikket',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
// Pages
'page_create' => 'maakte pagina',
- 'page_create_notification' => 'Pagina Succesvol Aangemaakt',
- 'page_update' => 'veranderde pagina',
- 'page_update_notification' => 'Pagina Succesvol Bijgewerkt',
+ 'page_create_notification' => 'Pagina succesvol aangemaakt',
+ 'page_update' => 'wijzigde pagina',
+ 'page_update_notification' => 'Pagina succesvol bijgewerkt',
'page_delete' => 'verwijderde pagina',
- 'page_delete_notification' => 'Pagina Succesvol Verwijderd',
+ 'page_delete_notification' => 'Pagina succesvol verwijderd',
'page_restore' => 'herstelde pagina',
- 'page_restore_notification' => 'Pagina Succesvol Hersteld',
+ 'page_restore_notification' => 'Pagina succesvol hersteld',
'page_move' => 'verplaatste pagina',
// Chapters
'chapter_create' => 'maakte hoofdstuk',
- 'chapter_create_notification' => 'Hoofdstuk Succesvol Aangemaakt',
- 'chapter_update' => 'veranderde hoofdstuk',
- 'chapter_update_notification' => 'Hoofdstuk Succesvol Bijgewerkt',
+ 'chapter_create_notification' => 'Hoofdstuk succesvol aangemaakt',
+ 'chapter_update' => 'wijzigde hoofdstuk',
+ 'chapter_update_notification' => 'Hoofdstuk succesvol bijgewerkt',
'chapter_delete' => 'verwijderde hoofdstuk',
- 'chapter_delete_notification' => 'Hoofdstuk Succesvol Verwijderd',
+ 'chapter_delete_notification' => 'Hoofdstuk succesvol verwijderd',
'chapter_move' => 'verplaatste hoofdstuk',
// Books
'book_create' => 'maakte boek',
- 'book_create_notification' => 'Boek Succesvol Aangemaakt',
- 'book_update' => 'veranderde boek',
- 'book_update_notification' => 'Boek Succesvol Bijgewerkt',
+ 'book_create_notification' => 'Boek succesvol aangemaakt',
+ 'book_update' => 'wijzigde boek',
+ 'book_update_notification' => 'Boek succesvol bijgewerkt',
'book_delete' => 'verwijderde boek',
- 'book_delete_notification' => 'Boek Succesvol Verwijderd',
+ 'book_delete_notification' => 'Boek succesvol verwijderd',
'book_sort' => 'sorteerde boek',
- 'book_sort_notification' => 'Boek Succesvol Gesorteerd',
+ 'book_sort_notification' => 'Boek succesvol gesorteerd',
// Bookshelves
- 'bookshelf_create' => 'maakte Boekenplank',
- 'bookshelf_create_notification' => 'Boekenplank Succesvol Aangemaakt',
- 'bookshelf_update' => 'veranderde boekenplank',
- 'bookshelf_update_notification' => 'Boekenplank Succesvol Bijgewerkt',
+ 'bookshelf_create' => 'maakte boekenplank',
+ 'bookshelf_create_notification' => 'Boekenplank succesvol aangemaakt',
+ 'bookshelf_update' => 'wijzigde boekenplank',
+ 'bookshelf_update_notification' => 'Boekenplank succesvol bijgewerkt',
'bookshelf_delete' => 'verwijderde boekenplank',
- 'bookshelf_delete_notification' => 'Boekenplank Succesvol Verwijderd',
+ 'bookshelf_delete_notification' => 'Boekenplank succesvol verwijderd',
+
+ // Favourites
+ 'favourite_add_notification' => '":name" is toegevoegd aan je favorieten',
+ 'favourite_remove_notification' => '":name" is verwijderd uit je favorieten',
// Other
- 'commented_on' => 'reactie op',
- 'permissions_update' => 'updated permissions',
+ 'commented_on' => 'reageerde op',
+ 'permissions_update' => 'wijzigde permissies',
];
return [
'failed' => 'Deze inloggegevens zijn niet bij ons bekend.',
- 'throttle' => 'Te veel loginpogingen! Probeer het opnieuw na :seconds seconden.',
+ 'throttle' => 'Te veel login pogingen! Probeer het opnieuw na :seconds seconden.',
// Login & Register
'sign_up' => 'Registreren',
'username' => 'Gebruikersnaam',
'email' => 'E-mail',
'password' => 'Wachtwoord',
- 'password_confirm' => 'Wachtwoord Bevestigen',
+ 'password_confirm' => 'Wachtwoord bevestigen',
'password_hint' => 'Minimaal 8 tekens',
'forgot_password' => 'Wachtwoord vergeten?',
'remember_me' => 'Mij onthouden',
- 'ldap_email_hint' => 'Geef een email op waarmee je dit account wilt gebruiken.',
- 'create_account' => 'Account Aanmaken',
+ 'ldap_email_hint' => 'Geef een emailadres op voor dit account.',
+ 'create_account' => 'Account aanmaken',
'already_have_account' => 'Heb je al een account?',
'dont_have_account' => 'Nog geen account?',
'social_login' => 'Aanmelden via een sociaal netwerk',
- 'social_registration' => 'Social Registratie',
- 'social_registration_text' => 'Registreer en log in met een andere dienst.',
+ 'social_registration' => 'Social registratie',
+ 'social_registration_text' => 'Registreer en log in met een andere service.',
'register_thanks' => 'Bedankt voor het registreren!',
'register_confirm' => 'Controleer je e-mail en bevestig je registratie om in te loggen op :appName.',
'registrations_disabled' => 'Registratie is momenteel niet mogelijk',
'registration_email_domain_invalid' => 'Dit e-maildomein is niet toegestaan',
- 'register_success' => 'Bedankt voor het inloggen. Je bent ook geregistreerd.',
+ 'register_success' => 'Bedankt voor het aanmelden! Je bent nu geregistreerd en aangemeld.',
// Password Reset
- 'reset_password' => 'Wachtwoord Herstellen',
+ 'reset_password' => 'Wachtwoord herstellen',
'reset_password_send_instructions' => 'Geef je e-mail en we sturen je een link om je wachtwoord te herstellen',
- 'reset_password_send_button' => 'Link Sturen',
+ 'reset_password_send_button' => 'Link sturen',
'reset_password_sent' => 'Een link om het wachtwoord te resetten zal verstuurd worden naar :email als dat e-mailadres in het systeem gevonden is.',
'reset_password_success' => 'Je wachtwoord is succesvol hersteld.',
'email_reset_subject' => 'Herstel je wachtwoord van :appName',
- 'email_reset_text' => 'Je ontvangt deze e-mail zodat je je wachtwoord kunt herstellen.',
- 'email_reset_not_requested' => 'Als je jouw wachtwoord niet wilt wijzigen, doe dan niets.',
+ 'email_reset_text' => 'Je ontvangt deze e-mail omdat je een wachtwoord herstel verzoek had verzonden.',
+ 'email_reset_not_requested' => 'Als je geen wachtwoord herstel hebt aangevraagd, hoef je niets te doen.',
// Email Confirmation
'email_confirm_text' => 'Bevestig je registratie door op onderstaande knop te drukken:',
'email_confirm_action' => 'Bevestig je e-mail',
'email_confirm_send_error' => 'E-mail bevestiging is vereisd maar het systeem kon geen mail verzenden. Neem contact op met de beheerder.',
- 'email_confirm_success' => 'Je e-mailadres is bevestigt!',
+ 'email_confirm_success' => 'Je e-mailadres is bevestigd!',
'email_confirm_resent' => 'De bevestigingse-mails is opnieuw verzonden. Controleer je inbox.',
- 'email_not_confirmed' => 'E-mail nog niet bevestigd',
+ 'email_not_confirmed' => 'E-mailadres nog niet bevestigd',
'email_not_confirmed_text' => 'Je e-mailadres is nog niet bevestigd.',
'email_not_confirmed_click_link' => 'Klik op de link in de e-mail die vlak na je registratie is verstuurd.',
'email_not_confirmed_resend' => 'Als je deze e-mail niet kunt vinden kun je deze met onderstaande formulier opnieuw verzenden.',
- 'email_not_confirmed_resend_button' => 'Bevestigingsmail Opnieuw Verzenden',
+ 'email_not_confirmed_resend_button' => 'Bevestigingsmail opnieuw verzenden',
// User Invite
'user_invite_email_subject' => 'Je bent uitgenodigd voor :appName!',
'save' => 'Opslaan',
'continue' => 'Doorgaan',
'select' => 'Kies',
- 'toggle_all' => 'Toggle Alles',
+ 'toggle_all' => 'Toggle alles',
'more' => 'Meer',
// Form Labels
'description' => 'Beschrijving',
'role' => 'Rol',
'cover_image' => 'Omslagfoto',
- 'cover_image_description' => 'Deze afbeelding moet ongeveer 300x170px zijn.',
+ 'cover_image_description' => 'Deze afbeelding moet ongeveer 440x250px zijn.',
// Actions
'actions' => 'Acties',
'view' => 'Bekijk',
- 'view_all' => 'Bekijk Alle',
+ 'view_all' => 'Bekijk alle',
'create' => 'Aanmaken',
'update' => 'Bijwerken',
'edit' => 'Bewerk',
'copy' => 'Kopiëren',
'reply' => 'Beantwoorden',
'delete' => 'Verwijder',
- 'delete_confirm' => 'Confirm Deletion',
+ 'delete_confirm' => 'Verwijdering bevestigen',
'search' => 'Zoek',
'search_clear' => 'Zoekopdracht wissen',
'reset' => 'Resetten',
'remove' => 'Verwijderen',
'add' => 'Toevoegen',
'fullscreen' => 'Volledig scherm',
+ 'favourite' => 'Favoriet',
+ 'unfavourite' => 'Verwijderen uit favoriet',
+ 'next' => 'Volgende',
+ 'previous' => 'Vorige',
// Sort Options
'sort_options' => 'Sorteeropties',
- 'sort_direction_toggle' => 'Sorteer richting',
+ 'sort_direction_toggle' => 'Sorteerrichting',
'sort_ascending' => 'Sorteer oplopend',
- 'sort_descending' => 'Sorteer teruglopend',
+ 'sort_descending' => 'Sorteer aflopend',
'sort_name' => 'Naam',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Standaard',
'sort_created_at' => 'Aanmaakdatum',
'sort_updated_at' => 'Gewijzigd op',
// Misc
'deleted_user' => 'Verwijderde gebruiker',
- 'no_activity' => 'Geen activiteiten',
+ 'no_activity' => 'Geen activiteit om weer te geven',
'no_items' => 'Geen items beschikbaar',
'back_to_top' => 'Terug naar boven',
- 'toggle_details' => 'Details Weergeven',
- 'toggle_thumbnails' => 'Thumbnails Weergeven',
+ 'toggle_details' => 'Details weergeven',
+ 'toggle_thumbnails' => 'Thumbnails weergeven',
'details' => 'Details',
'grid_view' => 'Grid weergave',
- 'list_view' => 'Lijst weergave',
+ 'list_view' => 'Lijstweergave',
'default' => 'Standaard',
'breadcrumb' => 'Kruimelpad',
// Header
+ 'header_menu_expand' => 'Header menu uitvouwen',
'profile_menu' => 'Profiel menu',
- 'view_profile' => 'Profiel Weergeven',
- 'edit_profile' => 'Profiel Bewerken',
- 'dark_mode' => 'Donkere Modus',
- 'light_mode' => 'Lichte Modus',
+ 'view_profile' => 'Profiel weergeven',
+ 'edit_profile' => 'Profiel bewerken',
+ 'dark_mode' => 'Donkere modus',
+ 'light_mode' => 'Lichte modus',
// Layout tabs
'tab_info' => 'Info',
+ 'tab_info_label' => 'Tabblad: Toon secundaire informatie',
'tab_content' => 'Inhoud',
+ 'tab_content_label' => 'Tabblad: Toon primaire inhoud',
// Email Content
- 'email_action_help' => 'Als je de knop ":actionText" niet werkt, kopieer en plak de onderstaande URL in je web browser:',
+ 'email_action_help' => 'Als je de knop ":actionText" niet werkt, kopieër en plak de onderstaande URL in je web browser:',
'email_rights' => 'Alle rechten voorbehouden',
// Footer Link Options
// Not directly used but available for convenience to users.
- 'privacy_policy' => 'Privacy Policy',
- 'terms_of_service' => 'Terms of Service',
+ 'privacy_policy' => 'Privacybeleid',
+ 'terms_of_service' => 'Algemene voorwaarden',
];
return [
// Image Manager
- 'image_select' => 'Selecteer Afbeelding',
+ 'image_select' => 'Selecteer afbeelding',
'image_all' => 'Alles',
'image_all_title' => 'Alle afbeeldingen weergeven',
'image_book_title' => 'Afbeeldingen van dit boek weergeven',
'image_page_title' => 'Afbeeldingen van deze pagina weergeven',
'image_search_hint' => 'Zoek op afbeeldingsnaam',
'image_uploaded' => 'Geüpload :uploadedDate',
- 'image_load_more' => 'Meer Laden',
+ 'image_load_more' => 'Meer laden',
'image_image_name' => 'Afbeeldingsnaam',
'image_delete_used' => 'Deze afbeeldingen is op onderstaande pagina\'s in gebruik.',
'image_delete_confirm_text' => 'Weet u zeker dat u deze afbeelding wilt verwijderen?',
- 'image_select_image' => 'Kies Afbeelding',
+ 'image_select_image' => 'Kies afbeelding',
'image_dropzone' => 'Sleep afbeeldingen hier of klik hier om te uploaden',
- 'images_deleted' => 'Verwijderde Afbeeldingen',
- 'image_preview' => 'Afbeelding Voorbeeld',
+ 'images_deleted' => 'Verwijderde afbeeldingen',
+ 'image_preview' => 'Afbeelding voorbeeld',
'image_upload_success' => 'Afbeelding succesvol geüpload',
'image_update_success' => 'Afbeeldingsdetails succesvol verwijderd',
'image_delete_success' => 'Afbeelding succesvol verwijderd',
// Code Editor
'code_editor' => 'Code invoegen',
- 'code_language' => 'Code taal',
+ 'code_language' => 'Codetaal',
'code_content' => 'Code',
- 'code_session_history' => 'Zittingsgeschiedenis',
+ 'code_session_history' => 'Sessie geschiedenis',
'code_save' => 'Sla code op',
];
return [
// Shared
- 'recently_created' => 'Recent Aangemaakt',
- 'recently_created_pages' => 'Recent Aangemaakte Pagina\'s',
- 'recently_updated_pages' => 'Recent Bijgewerkte Pagina\'s',
- 'recently_created_chapters' => 'Recent Aangemaakte Hoofdstukken',
- 'recently_created_books' => 'Recent Aangemaakte Boeken',
- 'recently_created_shelves' => 'Recent Aangemaakte Boekenplanken',
- 'recently_update' => 'Recent Bijgewerkt',
- 'recently_viewed' => 'Recent Bekeken',
- 'recent_activity' => 'Recente Activiteit',
- 'create_now' => 'Maak er zelf één',
+ 'recently_created' => 'Recent aangemaakt',
+ 'recently_created_pages' => 'Recent aangemaakte pagina\'s',
+ 'recently_updated_pages' => 'Recent bijgewerkte pagina\'s',
+ 'recently_created_chapters' => 'Recent aangemaakte hoofdstukken',
+ 'recently_created_books' => 'Recent aangemaakte boeken',
+ 'recently_created_shelves' => 'Recent aangemaakte boekenplanken',
+ 'recently_update' => 'Recent bijgewerkt',
+ 'recently_viewed' => 'Recent bekeken',
+ 'recent_activity' => 'Recente activiteit',
+ 'create_now' => 'Maak er nu één',
'revisions' => 'Revisies',
'meta_revision' => 'Revisie #:revisionCount',
'meta_created' => 'Aangemaakt :timeLength',
'meta_created_name' => 'Aangemaakt: :timeLength door :user',
- 'meta_updated' => ':timeLength Aangepast',
+ 'meta_updated' => 'Aangepast: :timeLength',
'meta_updated_name' => 'Aangepast: :timeLength door :user',
- 'meta_owned_name' => 'Owned by :user',
- 'entity_select' => 'Entiteit Selecteren',
+ 'meta_owned_name' => 'Eigendom van :user',
+ 'entity_select' => 'Entiteit selecteren',
'images' => 'Afbeeldingen',
- 'my_recent_drafts' => 'Mijn Concepten',
- 'my_recently_viewed' => 'Mijn Recent Bekeken',
+ 'my_recent_drafts' => 'Mijn concepten',
+ 'my_recently_viewed' => 'Mijn recent bekeken',
+ 'my_most_viewed_favourites' => 'Mijn meest bekeken favorieten',
+ 'my_favourites' => 'Mijn favorieten',
'no_pages_viewed' => 'Je hebt nog niets bekeken',
'no_pages_recently_created' => 'Er zijn geen recent aangemaakte pagina\'s',
'no_pages_recently_updated' => 'Er zijn geen recente wijzigingen',
'export' => 'Exporteren',
- 'export_html' => 'Ingesloten Webbestand',
- 'export_pdf' => 'PDF Bestand',
- 'export_text' => 'Normaal Tekstbestand',
+ 'export_html' => 'Ingesloten webbestand',
+ 'export_pdf' => 'PDF bestand',
+ 'export_text' => 'Normaal tekstbestand',
// Permissions and restrictions
'permissions' => 'Permissies',
'permissions_intro' => 'Als je dit aanzet, dan gelden rol-permissies niet meer voor deze pagina.',
- 'permissions_enable' => 'Custom Permissies Aanzetten',
- 'permissions_save' => 'Permissies Opslaan',
- 'permissions_owner' => 'Owner',
+ 'permissions_enable' => 'Aangepaste permissies aanzetten',
+ 'permissions_save' => 'Permissies opslaan',
+ 'permissions_owner' => 'Eigenaar',
// Search
'search_results' => 'Zoekresultaten',
- 'search_total_results_found' => ':count resultaten gevonden|:count resultaten gevonden',
+ 'search_total_results_found' => ':count resultaten gevonden|:count totaal aantal resultaten gevonden',
'search_clear' => 'Zoekopdracht wissen',
'search_no_pages' => 'Er zijn geen pagina\'s gevonden',
'search_for_term' => 'Zoeken op :term',
'search_advanced' => 'Uitgebreid zoeken',
'search_terms' => 'Zoektermen',
'search_content_type' => 'Inhoudstype',
- 'search_exact_matches' => 'Exacte Matches',
+ 'search_exact_matches' => 'Exacte matches',
'search_tags' => 'Zoek tags',
'search_options' => 'Opties',
'search_viewed_by_me' => 'Bekeken door mij',
'search_not_viewed_by_me' => 'Niet bekeken door mij',
- 'search_permissions_set' => 'Permissies gezet',
+ 'search_permissions_set' => 'Permissies ingesteld',
'search_created_by_me' => 'Door mij gemaakt',
'search_updated_by_me' => 'Door mij geupdate',
- 'search_owned_by_me' => 'Owned by me',
- 'search_date_options' => 'Datum Opties',
+ 'search_owned_by_me' => 'Eigendom van mij',
+ 'search_date_options' => 'Datum opties',
'search_updated_before' => 'Geupdate voor',
'search_updated_after' => 'Geupdate na',
'search_created_before' => 'Gecreëerd voor',
'x_shelves' => ':count Boekenplank|:count Boekenplanken',
'shelves_long' => 'Boekenplanken',
'shelves_empty' => 'Er zijn geen boekenplanken aangemaakt',
- 'shelves_create' => 'Nieuwe Boekenplank Aanmaken',
- 'shelves_popular' => 'Populaire Boekenplanken',
- 'shelves_new' => 'Nieuwe Boekenplanken',
- 'shelves_new_action' => 'Nieuwe Boekplank',
+ 'shelves_create' => 'Nieuwe boekenplank maken',
+ 'shelves_popular' => 'Populaire boekenplanken',
+ 'shelves_new' => 'Nieuwe boekenplanken',
+ 'shelves_new_action' => 'Nieuwe boekenplank',
'shelves_popular_empty' => 'De meest populaire boekenplanken worden hier weergegeven.',
'shelves_new_empty' => 'De meest recent aangemaakt boekenplanken worden hier weergeven.',
- 'shelves_save' => 'Boekenplanken Opslaan',
+ 'shelves_save' => 'Boekenplank opslaan',
'shelves_books' => 'Boeken op deze plank',
- 'shelves_add_books' => 'Toevoegen boeken aan deze plank',
- 'shelves_drag_books' => 'Sleep boeken hier naartoe om deze toe te voegen aan deze plank',
+ 'shelves_add_books' => 'Voeg boeken toe aan deze plank',
+ 'shelves_drag_books' => 'Sleep boeken hiernaartoe om deze toe te voegen aan deze plank',
'shelves_empty_contents' => 'Er zijn geen boeken aan deze plank toegekend',
'shelves_edit_and_assign' => 'Bewerk boekenplank om boeken toe te kennen.',
- 'shelves_edit_named' => 'Bewerk Boekenplank :name',
- 'shelves_edit' => 'Bewerk Boekenplank',
- 'shelves_delete' => 'Verwijder Boekenplank',
- 'shelves_delete_named' => 'Verwijder Boekenplank :name',
+ 'shelves_edit_named' => 'Bewerk boekenplank :name',
+ 'shelves_edit' => 'Bewerk boekenplank',
+ 'shelves_delete' => 'Verwijder boekenplank',
+ 'shelves_delete_named' => 'Verwijder boekenplank :name',
'shelves_delete_explain' => "Deze actie verwijdert de boekenplank met naam ':name'. De boeken op deze plank worden niet verwijderd.",
'shelves_delete_confirmation' => 'Weet je zeker dat je deze boekenplank wilt verwijderen?',
- 'shelves_permissions' => 'Boekenplank Permissies',
- 'shelves_permissions_updated' => 'Boekenplank Permissies Opgeslagen',
- 'shelves_permissions_active' => 'Boekenplank Permissies Actief',
- 'shelves_copy_permissions_to_books' => 'Kopieer Permissies naar Boeken',
- 'shelves_copy_permissions' => 'Kopieer Permissies',
- 'shelves_copy_permissions_explain' => 'Met deze actie worden de permissies van deze boekenplank gekopieerd naar alle boeken op de plank. Voordat deze actie wordt uitgevoerd, zorg dat de wijzigingen in de permissies van deze boekenplank zijn opgeslagen.',
- 'shelves_copy_permission_success' => 'Boekenplank permissies gekopieerd naar :count boeken',
+ 'shelves_permissions' => 'Boekenplank permissies',
+ 'shelves_permissions_updated' => 'Boekenplank permissies opgeslagen',
+ 'shelves_permissions_active' => 'Boekenplank permissies actief',
+ 'shelves_copy_permissions_to_books' => 'Kopieer permissies naar boeken',
+ 'shelves_copy_permissions' => 'Kopieer permissies',
+ 'shelves_copy_permissions_explain' => 'Met deze actie worden de permissies van deze boekenplank gekopieërd naar alle boeken op de plank. Voordat deze actie wordt uitgevoerd, zorg dat de wijzigingen in de permissies van deze boekenplank zijn opgeslagen.',
+ 'shelves_copy_permission_success' => 'Boekenplank permissies gekopieërd naar :count boeken',
// Books
'book' => 'Boek',
'books' => 'Boeken',
'x_books' => ':count Boek|:count Boeken',
'books_empty' => 'Er zijn geen boeken aangemaakt',
- 'books_popular' => 'Populaire Boeken',
- 'books_recent' => 'Recente Boeken',
- 'books_new' => 'Nieuwe Boeken',
- 'books_new_action' => 'Nieuw Boek',
+ 'books_popular' => 'Populaire boeken',
+ 'books_recent' => 'Recente boeken',
+ 'books_new' => 'Nieuwe boeken',
+ 'books_new_action' => 'Nieuw boek',
'books_popular_empty' => 'De meest populaire boeken worden hier weergegeven.',
'books_new_empty' => 'De meest recent aangemaakte boeken verschijnen hier.',
- 'books_create' => 'Nieuw Boek Aanmaken',
- 'books_delete' => 'Boek Verwijderen',
- 'books_delete_named' => 'Verwijder Boek :bookName',
+ 'books_create' => 'Nieuw boek maken',
+ 'books_delete' => 'Boek verwijderen',
+ 'books_delete_named' => 'Verwijder boek :bookName',
'books_delete_explain' => 'Deze actie verwijdert het boek \':bookName\', Alle pagina\'s en hoofdstukken worden verwijderd.',
'books_delete_confirmation' => 'Weet je zeker dat je dit boek wilt verwijderen?',
- 'books_edit' => 'Boek Bewerken',
- 'books_edit_named' => 'Bewerkt Boek :bookName',
- 'books_form_book_name' => 'Boek Naam',
- 'books_save' => 'Boek Opslaan',
- 'books_permissions' => 'Boek Permissies',
- 'books_permissions_updated' => 'Boek Permissies Opgeslagen',
- 'books_empty_contents' => 'Er zijn nog een hoofdstukken en pagina\'s voor dit boek gemaakt.',
- 'books_empty_create_page' => 'Pagina Toevoegen',
+ 'books_edit' => 'Boek bewerken',
+ 'books_edit_named' => 'Bewerk boek :bookName',
+ 'books_form_book_name' => 'Boek naam',
+ 'books_save' => 'Boek opslaan',
+ 'books_permissions' => 'Boek permissies',
+ 'books_permissions_updated' => 'Boek permissies opgeslagen',
+ 'books_empty_contents' => 'Er zijn nog geen hoofdstukken en pagina\'s voor dit boek gemaakt.',
+ 'books_empty_create_page' => 'Nieuwe pagina maken',
'books_empty_sort_current_book' => 'Boek sorteren',
- 'books_empty_add_chapter' => 'Hoofdstuk Toevoegen',
- 'books_permissions_active' => 'Boek Permissies Actief',
+ 'books_empty_add_chapter' => 'Hoofdstuk toevoegen',
+ 'books_permissions_active' => 'Boek permissies actief',
'books_search_this' => 'Zoeken in dit boek',
- 'books_navigation' => 'Boek Navigatie',
+ 'books_navigation' => 'Boek navigatie',
'books_sort' => 'Inhoud van het boek sorteren',
- 'books_sort_named' => 'Sorteer Boek :bookName',
- 'books_sort_name' => 'Sorteren op Naam',
+ 'books_sort_named' => 'Sorteer boek :bookName',
+ 'books_sort_name' => 'Sorteren op naam',
'books_sort_created' => 'Sorteren op datum van aanmaken',
'books_sort_updated' => 'Sorteren op datum van bijgewerkt',
'books_sort_chapters_first' => 'Hoofdstukken eerst',
- 'books_sort_chapters_last' => 'Hoofdstukken Laatst',
- 'books_sort_show_other' => 'Bekijk Andere Boeken',
- 'books_sort_save' => 'Nieuwe Order Opslaan',
+ 'books_sort_chapters_last' => 'Hoofdstukken laatst',
+ 'books_sort_show_other' => 'Bekijk andere boeken',
+ 'books_sort_save' => 'Nieuwe volgorde opslaan',
// Chapters
'chapter' => 'Hoofdstuk',
'chapters' => 'Hoofdstukken',
'x_chapters' => ':count Hoofdstuk|:count Hoofdstukken',
- 'chapters_popular' => 'Populaire Hoofdstukken',
- 'chapters_new' => 'Nieuw Hoofdstuk',
- 'chapters_create' => 'Hoofdstuk Toevoegen',
- 'chapters_delete' => 'Hoofdstuk Verwijderen',
- 'chapters_delete_named' => 'Verwijder Hoofdstuk :chapterName',
- 'chapters_delete_explain' => 'This will delete the chapter with the name \':chapterName\'. All pages that exist within this chapter will also be deleted.',
+ 'chapters_popular' => 'Populaire hoofdstukken',
+ 'chapters_new' => 'Nieuw hoofdstuk',
+ 'chapters_create' => 'Nieuw hoofdstuk maken',
+ 'chapters_delete' => 'Hoofdstuk verwijderen',
+ 'chapters_delete_named' => 'Verwijder hoofdstuk :chapterName',
+ 'chapters_delete_explain' => 'Dit verwijdert het hoofdstuk met de naam \':chapterName\'. Alle pagina\'s die binnen dit hoofdstuk staan, worden ook verwijderd.',
'chapters_delete_confirm' => 'Weet je zeker dat je dit boek wilt verwijderen?',
- 'chapters_edit' => 'Hoofdstuk Aanpassen',
- 'chapters_edit_named' => 'Hoofdstuk :chapterName Aanpassen',
- 'chapters_save' => 'Hoofdstuk Opslaan',
- 'chapters_move' => 'Hoofdstuk Verplaatsen',
- 'chapters_move_named' => 'Verplaatst Hoofdstuk :chapterName',
- 'chapter_move_success' => 'Hoofdstuk Verplaatst Naar :bookName',
- 'chapters_permissions' => 'Hoofdstuk Permissies',
+ 'chapters_edit' => 'Hoofdstuk aanpassen',
+ 'chapters_edit_named' => 'Hoofdstuk :chapterName aanpassen',
+ 'chapters_save' => 'Hoofdstuk opslaan',
+ 'chapters_move' => 'Hoofdstuk verplaatsen',
+ 'chapters_move_named' => 'Verplaatst hoofdstuk :chapterName',
+ 'chapter_move_success' => 'Hoofdstuk verplaatst naar :bookName',
+ 'chapters_permissions' => 'Hoofdstuk permissies',
'chapters_empty' => 'Er zijn geen pagina\'s in dit hoofdstuk aangemaakt.',
- 'chapters_permissions_active' => 'Hoofdstuk Permissies Actief',
- 'chapters_permissions_success' => 'Hoofdstuk Permissies Bijgewerkt',
+ 'chapters_permissions_active' => 'Hoofdstuk permissies actief',
+ 'chapters_permissions_success' => 'Hoofdstuk permissies bijgewerkt',
'chapters_search_this' => 'Doorzoek dit hoofdstuk',
// Pages
'page' => 'Pagina',
'pages' => 'Pagina\'s',
'x_pages' => ':count Pagina|:count Pagina\'s',
- 'pages_popular' => 'Populaire Pagina\'s',
- 'pages_new' => 'Nieuwe Pagina',
+ 'pages_popular' => 'Populaire pagina\'s',
+ 'pages_new' => 'Nieuwe pagina',
'pages_attachments' => 'Bijlages',
- 'pages_navigation' => 'Pagina Navigatie',
- 'pages_delete' => 'Pagina Verwijderen',
- 'pages_delete_named' => 'Verwijderde Pagina :pageName',
- 'pages_delete_draft_named' => 'Verwijderde Conceptpagina :pageName',
- 'pages_delete_draft' => 'Verwijder Conceptpagina',
+ 'pages_navigation' => 'Pagina navigatie',
+ 'pages_delete' => 'Pagina verwijderen',
+ 'pages_delete_named' => 'Verwijderd pagina :pageName',
+ 'pages_delete_draft_named' => 'Verwijder concept pagina :pageName',
+ 'pages_delete_draft' => 'Verwijder concept pagina',
'pages_delete_success' => 'Pagina verwijderd',
'pages_delete_draft_success' => 'Concept verwijderd',
'pages_delete_confirm' => 'Weet je zeker dat je deze pagina wilt verwijderen?',
'pages_delete_draft_confirm' => 'Weet je zeker dat je dit concept wilt verwijderen?',
- 'pages_editing_named' => 'Pagina :pageName Bewerken',
- 'pages_edit_draft_options' => 'Concept Opties',
+ 'pages_editing_named' => 'Pagina :pageName bewerken',
+ 'pages_edit_draft_options' => 'Concept opties',
'pages_edit_save_draft' => 'Concept opslaan',
- 'pages_edit_draft' => 'Paginaconcept Bewerken',
- 'pages_editing_draft' => 'Concept Bewerken',
- 'pages_editing_page' => 'Concept Bewerken',
+ 'pages_edit_draft' => 'Paginaconcept bewerken',
+ 'pages_editing_draft' => 'Concept bewerken',
+ 'pages_editing_page' => 'Concept bewerken',
'pages_edit_draft_save_at' => 'Concept opgeslagen op ',
- 'pages_edit_delete_draft' => 'Concept Verwijderen',
- 'pages_edit_discard_draft' => 'Concept Verwijderen',
+ 'pages_edit_delete_draft' => 'Concept verwijderen',
+ 'pages_edit_discard_draft' => 'Concept verwijderen',
'pages_edit_set_changelog' => 'Changelog',
'pages_edit_enter_changelog_desc' => 'Geef een korte omschrijving van de wijzingen die je gemaakt hebt.',
- 'pages_edit_enter_changelog' => 'Zie logboek',
- 'pages_save' => 'Pagina Opslaan',
- 'pages_title' => 'Pagina Titel',
- 'pages_name' => 'Pagina Naam',
- 'pages_md_editor' => 'Bewerker',
+ 'pages_edit_enter_changelog' => 'Zie changelog',
+ 'pages_save' => 'Pagina opslaan',
+ 'pages_title' => 'Pagina titel',
+ 'pages_name' => 'Pagina naam',
+ 'pages_md_editor' => 'Bewerken',
'pages_md_preview' => 'Voorbeeld',
- 'pages_md_insert_image' => 'Afbeelding Invoegen',
- 'pages_md_insert_link' => 'Entity Link Invoegen',
- 'pages_md_insert_drawing' => 'Tekening Toevoegen',
+ 'pages_md_insert_image' => 'Afbeelding invoegen',
+ 'pages_md_insert_link' => 'Entity link invoegen',
+ 'pages_md_insert_drawing' => 'Tekening invoegen',
'pages_not_in_chapter' => 'Deze pagina staat niet in een hoofdstuk',
- 'pages_move' => 'Pagina Verplaatsten',
+ 'pages_move' => 'Pagina verplaatsten',
'pages_move_success' => 'Pagina verplaatst naar ":parentName"',
- 'pages_copy' => 'Pagina Kopiëren',
- 'pages_copy_desination' => 'Kopieerbestemming',
- 'pages_copy_success' => 'Pagina succesvol gekopieerd',
- 'pages_permissions' => 'Pagina Permissies',
- 'pages_permissions_success' => 'Pagina Permissies bijgwerkt',
+ 'pages_copy' => 'Pagina kopiëren',
+ 'pages_copy_desination' => 'Kopieër bestemming',
+ 'pages_copy_success' => 'Pagina succesvol gekopieërd',
+ 'pages_permissions' => 'Pagina permissies',
+ 'pages_permissions_success' => 'Pagina permissies bijgewerkt',
'pages_revision' => 'Revisie',
- 'pages_revisions' => 'Pagina Revisies',
- 'pages_revisions_named' => 'Pagina Revisies voor :pageName',
- 'pages_revision_named' => 'Pagina Revisie voor :pageName',
- 'pages_revision_restored_from' => 'Restored from #:id; :summary',
+ 'pages_revisions' => 'Pagina revisies',
+ 'pages_revisions_named' => 'Pagina revisies voor :pageName',
+ 'pages_revision_named' => 'Pagina revisie voor :pageName',
+ 'pages_revision_restored_from' => 'Hersteld van #:id; :samenvatting',
'pages_revisions_created_by' => 'Aangemaakt door',
'pages_revisions_date' => 'Revisiedatum',
'pages_revisions_number' => '#',
'pages_revisions_numbered' => 'Revisie #:id',
- 'pages_revisions_numbered_changes' => 'Revisie #:id Wijzigingen',
- 'pages_revisions_changelog' => 'Wijzigingslogboek',
+ 'pages_revisions_numbered_changes' => 'Revisie #:id wijzigingen',
+ 'pages_revisions_changelog' => 'Changelog',
'pages_revisions_changes' => 'Wijzigingen',
- 'pages_revisions_current' => 'Huidige Versie',
+ 'pages_revisions_current' => 'Huidige versie',
'pages_revisions_preview' => 'Voorbeeld',
'pages_revisions_restore' => 'Herstellen',
'pages_revisions_none' => 'Deze pagina heeft geen revisies',
- 'pages_copy_link' => 'Link Kopiëren',
+ 'pages_copy_link' => 'Link kopiëren',
'pages_edit_content_link' => 'Bewerk inhoud',
- 'pages_permissions_active' => 'Pagina Permissies Actief',
+ 'pages_permissions_active' => 'Pagina permissies actief',
'pages_initial_revision' => 'Eerste publicatie',
- 'pages_initial_name' => 'Nieuwe Pagina',
+ 'pages_initial_name' => 'Nieuwe pagina',
'pages_editing_draft_notification' => 'U bewerkt momenteel een concept dat voor het laatst is opgeslagen op :timeDiff.',
'pages_draft_edited_notification' => 'Deze pagina is sindsdien bijgewerkt. Het wordt aanbevolen dat u dit concept verwijderd.',
'pages_draft_edit_active' => [
'time_b' => 'in de laatste :minCount minuten',
'message' => ':start :time. Let op om elkaars updates niet te overschrijven!',
],
- 'pages_draft_discarded' => 'Concept verwijderd, de editor is bijgewerkt met de huidige pagina-inhoud',
- 'pages_specific' => 'Specifieke Pagina',
+ 'pages_draft_discarded' => 'Concept verwijderd, de editor is bijgewerkt met de huidige paginainhoud',
+ 'pages_specific' => 'Specifieke pagina',
'pages_is_template' => 'Paginasjabloon',
// Editor Sidebar
'page_tags' => 'Pagina Labels',
- 'chapter_tags' => 'Tags van Hoofdstuk',
- 'book_tags' => 'Tags van Boeken',
- 'shelf_tags' => 'Tags van Boekplanken',
+ 'chapter_tags' => 'Labels van hoofdstuk',
+ 'book_tags' => 'Labels van boeken',
+ 'shelf_tags' => 'Labels van boekenplanken',
'tag' => 'Label',
- 'tags' => 'Tags',
- 'tag_name' => 'Naam Tag',
- 'tag_value' => 'Label Waarde (Optioneel)',
+ 'tags' => 'Labels',
+ 'tag_name' => 'Naam label',
+ 'tag_value' => 'Labelwaarde (Optioneel)',
'tags_explain' => "Voeg labels toe om de inhoud te categoriseren. \n Je kunt meerdere labels toevoegen.",
'tags_add' => 'Voeg een extra label toe',
- 'tags_remove' => 'Deze tag verwijderen',
+ 'tags_remove' => 'Dit label verwijderen',
'attachments' => 'Bijlages',
'attachments_explain' => 'Upload bijlages of voeg een link toe. Deze worden zichtbaar in het navigatiepaneel.',
'attachments_explain_instant_save' => 'Wijzigingen worden meteen opgeslagen.',
'attachments_items' => 'Bijlages',
- 'attachments_upload' => 'Bestand Uploaden',
- 'attachments_link' => 'Link Toevoegen',
- 'attachments_set_link' => 'Zet Link',
+ 'attachments_upload' => 'Bestand uploaden',
+ 'attachments_link' => 'Link toevoegen',
+ 'attachments_set_link' => 'Zet link',
'attachments_delete' => 'Weet u zeker dat u deze bijlage wilt verwijderen?',
'attachments_dropzone' => 'Sleep hier een bestand of klik hier om een bestand toe te voegen',
'attachments_no_files' => 'Er zijn geen bestanden geüpload',
'attachments_explain_link' => 'Je kunt een link toevoegen als je geen bestanden wilt uploaden. Dit kan een link naar een andere pagina op deze website zijn, maar ook een link naar een andere website.',
- 'attachments_link_name' => 'Link Naam',
+ 'attachments_link_name' => 'Link naam',
'attachment_link' => 'Bijlage link',
'attachments_link_url' => 'Link naar bestand',
- 'attachments_link_url_hint' => 'Url, site of bestand',
+ 'attachments_link_url_hint' => 'URL van site of bestand',
'attach' => 'Koppelen',
- 'attachments_insert_link' => 'Add Attachment Link to Page',
- 'attachments_edit_file' => 'Bestand Bewerken',
+ 'attachments_insert_link' => 'Bijlage link toevoegen aan pagina',
+ 'attachments_edit_file' => 'Bestand bewerken',
'attachments_edit_file_name' => 'Bestandsnaam',
'attachments_edit_drop_upload' => 'Sleep een bestand of klik hier om te uploaden en te overschrijven',
'attachments_order_updated' => 'De volgorde van de bijlages is bijgewerkt',
// Comments
'comment' => 'Reactie',
'comments' => 'Reacties',
- 'comment_add' => 'Reactie Toevoegen',
+ 'comment_add' => 'Reactie toevoegen',
'comment_placeholder' => 'Laat hier een reactie achter',
'comment_count' => '{0} Geen reacties|{1} 1 Reactie|[2,*] :count Reacties',
'comment_save' => 'Sla reactie op',
'comment_deleted_success' => 'Reactie verwijderd',
'comment_created_success' => 'Reactie toegevoegd',
'comment_updated_success' => 'Reactie bijgewerkt',
- 'comment_delete_confirm' => 'Zeker reactie verwijderen?',
+ 'comment_delete_confirm' => 'Weet je zeker dat je deze reactie wilt verwijderen?',
'comment_in_reply_to' => 'Antwoord op :commentId',
// Revision
'saml_no_email_address' => 'Kan geen e-mailadres voor deze gebruiker vinden in de gegevens die door het externe verificatiesysteem worden verstrekt',
'saml_invalid_response_id' => 'Het verzoek van het externe verificatiesysteem is niet herkend door een door deze applicatie gestart proces. Het terug navigeren na een login kan dit probleem veroorzaken.',
'saml_fail_authed' => 'Inloggen met :system mislukt, het systeem gaf geen succesvolle autorisatie',
- 'social_no_action_defined' => 'Geen actie gedefineerd',
+ 'social_no_action_defined' => 'Geen actie gedefineërd',
'social_login_bad_response' => "Fout ontvangen tijdens :socialAccount login: \n:error",
'social_account_in_use' => 'Dit :socialAccount account is al in gebruik, Probeer in te loggen met de :socialAccount optie.',
'social_account_email_in_use' => 'Het e-mailadres :email is al in gebruik. Als je al een account hebt kun je een :socialAccount account verbinden met je profielinstellingen.',
'404_page_not_found' => 'Pagina Niet Gevonden',
'sorry_page_not_found' => 'Sorry, de pagina die je zocht is niet beschikbaar.',
'sorry_page_not_found_permission_warning' => 'Als u verwacht dat deze pagina bestaat heeft u misschien geen rechten om het te bekijken.',
+ 'image_not_found' => 'Afbeelding niet gevonden',
+ 'image_not_found_subtitle' => 'Sorry, de afbeelding die je zocht is niet beschikbaar.',
+ 'image_not_found_details' => 'Als u verwachtte dat deze afbeelding zou bestaan, dan is deze misschien verwijderd.',
'return_home' => 'Terug naar home',
'error_occurred' => 'Er Ging Iets Fout',
'app_down' => ':appName is nu niet beschikbaar',
'app_homepage' => 'Applicatie Homepagina',
'app_homepage_desc' => 'Selecteer een weergave om weer te geven op de homepage in plaats van de standaard weergave. Paginarechten worden genegeerd voor geselecteerde pagina\'s.',
'app_homepage_select' => 'Selecteer een pagina',
- 'app_footer_links' => 'Footer Links',
- 'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
- 'app_footer_links_label' => 'Link Label',
+ 'app_footer_links' => 'Voettekst links',
+ 'app_footer_links_desc' => 'Voeg links toe om te laten zien in de voettekst van de site. Deze worden onderaan de meeste pagina\'s weergegeven, met inbegrip van pagina\'s die geen inloggen vereisen. U kunt een label van "trans::<key>" gebruiken om systeemgedefinieerde vertalingen te gebruiken. Bijvoorbeeld: Het gebruik van "trans:common.privacy_policy" biedt de vertaalde tekst "Privacybeleid" en "trans:common.terms_of_service" voor de vertaalde tekst "Servicevoorwaarden".',
+ 'app_footer_links_label' => 'Link label',
'app_footer_links_url' => 'Link URL',
- 'app_footer_links_add' => 'Add Footer Link',
+ 'app_footer_links_add' => 'Voettekst link toevoegen',
'app_disable_comments' => 'Reacties uitschakelen',
'app_disable_comments_toggle' => 'Opmerkingen uitschakelen',
'app_disable_comments_desc' => 'Schakel opmerkingen uit op alle pagina\'s in de applicatie. Bestaande opmerkingen worden niet getoond.',
'maint' => 'Onderhoud',
'maint_image_cleanup' => 'Afbeeldingen opschonen',
'maint_image_cleanup_desc' => "Scant pagina- en revisie inhoud om te controleren welke afbeeldingen en tekeningen momenteel worden gebruikt en welke afbeeldingen overbodig zijn. Zorg ervoor dat je een volledige database en afbeelding backup maakt voordat je dit uitvoert.",
- 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
+ 'maint_delete_images_only_in_revisions' => 'Ook afbeeldingen die alleen in oude pagina revisies bestaan verwijderen',
'maint_image_cleanup_run' => 'Opschonen uitvoeren',
'maint_image_cleanup_warning' => ':count potentieel ongebruikte afbeeldingen gevonden. Weet u zeker dat u deze afbeeldingen wilt verwijderen?',
'maint_image_cleanup_success' => ':count potentieel ongebruikte afbeeldingen gevonden en verwijderd!',
'maint_send_test_email_mail_subject' => 'Test E-mail',
'maint_send_test_email_mail_greeting' => 'E-mailbezorging lijkt te werken!',
'maint_send_test_email_mail_text' => 'Gefeliciteerd! Nu je deze e-mailmelding hebt ontvangen, lijken je e-mailinstellingen correct te zijn geconfigureerd.',
- 'maint_recycle_bin_desc' => 'Deleted shelves, books, chapters & pages are sent to the recycle bin so they can be restored or permanently deleted. Older items in the recycle bin may be automatically removed after a while depending on system configuration.',
- 'maint_recycle_bin_open' => 'Open Recycle Bin',
+ 'maint_recycle_bin_desc' => 'Verwijderde planken, boeken, hoofdstukken en pagina\'s worden naar de prullenbak gestuurd om ze te herstellen of definitief te verwijderen. Oudere items in de prullenbak kunnen automatisch worden verwijderd, afhankelijk van de systeemconfiguratie.',
+ 'maint_recycle_bin_open' => 'Prullenbak openen',
// Recycle Bin
- 'recycle_bin' => 'Recycle Bin',
- 'recycle_bin_desc' => 'Here you can restore items that have been deleted or choose to permanently remove them from the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
- 'recycle_bin_deleted_item' => 'Deleted Item',
- 'recycle_bin_deleted_by' => 'Deleted By',
- 'recycle_bin_deleted_at' => 'Deletion Time',
- 'recycle_bin_permanently_delete' => 'Permanently Delete',
- 'recycle_bin_restore' => 'Restore',
- 'recycle_bin_contents_empty' => 'The recycle bin is currently empty',
- 'recycle_bin_empty' => 'Empty Recycle Bin',
- 'recycle_bin_empty_confirm' => 'This will permanently destroy all items in the recycle bin including content contained within each item. Are you sure you want to empty the recycle bin?',
- 'recycle_bin_destroy_confirm' => 'This action will permanently delete this item, along with any child elements listed below, from the system and you will not be able to restore this content. Are you sure you want to permanently delete this item?',
- 'recycle_bin_destroy_list' => 'Items to be Destroyed',
- 'recycle_bin_restore_list' => 'Items to be Restored',
- 'recycle_bin_restore_confirm' => 'This action will restore the deleted item, including any child elements, to their original location. If the original location has since been deleted, and is now in the recycle bin, the parent item will also need to be restored.',
- 'recycle_bin_restore_deleted_parent' => 'The parent of this item has also been deleted. These will remain deleted until that parent is also restored.',
- 'recycle_bin_destroy_notification' => 'Deleted :count total items from the recycle bin.',
- 'recycle_bin_restore_notification' => 'Restored :count total items from the recycle bin.',
+ 'recycle_bin' => 'Prullenbak',
+ 'recycle_bin_desc' => 'Hier kunt u items herstellen die zijn verwijderd of kiezen om ze permanent te verwijderen uit het systeem. Deze lijst is niet gefilterd, in tegenstelling tot vergelijkbare activiteitenlijsten in het systeem waar rechtenfilters worden toegepast.',
+ 'recycle_bin_deleted_item' => 'Verwijderde Item',
+ 'recycle_bin_deleted_by' => 'Verwijderd door',
+ 'recycle_bin_deleted_at' => 'Verwijdert op',
+ 'recycle_bin_permanently_delete' => 'Permanent verwijderen',
+ 'recycle_bin_restore' => 'Herstellen',
+ 'recycle_bin_contents_empty' => 'De prullenbak is momenteel leeg',
+ 'recycle_bin_empty' => 'Prullenbak legen',
+ 'recycle_bin_empty_confirm' => 'Dit zal permanent alle items in de prullenbak vernietigen, inclusief inhoud die in elk item zit. Weet u zeker dat u de prullenbak wilt legen?',
+ 'recycle_bin_destroy_confirm' => 'Deze actie zal dit item permanent verwijderen, samen met alle onderliggende elementen hieronder vanuit het systeem en u kunt deze inhoud niet herstellen. Weet u zeker dat u dit item permanent wilt verwijderen?',
+ 'recycle_bin_destroy_list' => 'Te vernietigen objecten',
+ 'recycle_bin_restore_list' => 'Items te herstellen',
+ 'recycle_bin_restore_confirm' => 'Deze actie herstelt het verwijderde item, inclusief alle onderliggende elementen, op hun oorspronkelijke locatie. Als de oorspronkelijke locatie sindsdien is verwijderd en zich nu in de prullenbak bevindt, zal ook het bovenliggende item moeten worden hersteld.',
+ 'recycle_bin_restore_deleted_parent' => 'De bovenliggende map van dit item is ook verwijderd. Deze zal worden verwijderd totdat het bovenliggende item ook is hersteld.',
+ 'recycle_bin_destroy_notification' => 'Verwijderde totaal :count items uit de prullenbak.',
+ 'recycle_bin_restore_notification' => 'Herstelde totaal :count items uit de prullenbak.',
// Audit Log
'audit' => 'Audit Log',
- 'audit_desc' => 'This audit log displays a list of activities tracked in the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
- 'audit_event_filter' => 'Event Filter',
- 'audit_event_filter_no_filter' => 'No Filter',
- 'audit_deleted_item' => 'Deleted Item',
- 'audit_deleted_item_name' => 'Name: :name',
- 'audit_table_user' => 'User',
- 'audit_table_event' => 'Event',
- 'audit_table_related' => 'Related Item or Detail',
- 'audit_table_date' => 'Activity Date',
- 'audit_date_from' => 'Date Range From',
- 'audit_date_to' => 'Date Range To',
+ 'audit_desc' => 'Dit auditlogboek toont een lijst met activiteiten die in het systeem zijn gedaan. Deze lijst is niet gefilterd, in tegenstelling tot vergelijkbare activiteitenlijsten in het systeem waar rechtenfilters worden toegepast.',
+ 'audit_event_filter' => 'Gebeurtenis filter',
+ 'audit_event_filter_no_filter' => 'Geen filter',
+ 'audit_deleted_item' => 'Verwijderd Item',
+ 'audit_deleted_item_name' => 'Naam: :name',
+ 'audit_table_user' => 'Gebruiker',
+ 'audit_table_event' => 'Gebeurtenis',
+ 'audit_table_related' => 'Gerelateerd Item of Detail',
+ 'audit_table_date' => 'Activiteit datum',
+ 'audit_date_from' => 'Datum bereik vanaf',
+ 'audit_date_to' => 'Datum bereik tot',
// Role Settings
'roles' => 'Rollen',
'role_access_api' => 'Ga naar systeem API',
'role_manage_settings' => 'Beheer app instellingen',
'role_asset' => 'Asset Permissies',
- 'roles_system_warning' => 'Be aware that access to any of the above three permissions can allow a user to alter their own privileges or the privileges of others in the system. Only assign roles with these permissions to trusted users.',
+ 'roles_system_warning' => 'Wees ervan bewust dat toegang tot een van de bovengenoemde drie machtigingen een gebruiker in staat kan stellen zijn eigen privileges of de privileges van anderen in het systeem te wijzigen. Wijs alleen rollen toe met deze machtigingen aan vertrouwde gebruikers.',
'role_asset_desc' => 'Deze permissies bepalen de standaardtoegangsrechten. Permissies op boeken, hoofdstukken en pagina\'s overschrijven deze instelling.',
'role_asset_admins' => 'Beheerders krijgen automatisch toegang tot alle inhoud, maar deze opties kunnen interface opties tonen of verbergen.',
'role_all' => 'Alles',
'user_profile' => 'Gebruikersprofiel',
'users_add_new' => 'Gebruiker toevoegen',
'users_search' => 'Gebruiker zoeken',
- 'users_latest_activity' => 'Latest Activity',
+ 'users_latest_activity' => 'Laatste activiteit',
'users_details' => 'Gebruiker details',
'users_details_desc' => 'Stel een weergavenaam en e-mailadres in voor deze gebruiker. Het e-mailadres zal worden gebruikt om in te loggen.',
'users_details_desc_no_email' => 'Stel een weergavenaam in voor deze gebruiker zodat anderen deze kunnen herkennen.',
'users_send_invite_text' => 'U kunt ervoor kiezen om deze gebruiker een uitnodigingsmail te sturen waarmee hij zijn eigen wachtwoord kan instellen, anders kunt u zelf zijn wachtwoord instellen.',
'users_send_invite_option' => 'Stuur gebruiker uitnodigings e-mail',
'users_external_auth_id' => 'Externe authenticatie ID',
- 'users_external_auth_id_desc' => 'This is the ID used to match this user when communicating with your external authentication system.',
+ 'users_external_auth_id_desc' => 'Dit is het ID dat gebruikt wordt om deze gebruiker te vergelijken met uw externe verificatiesysteem.',
'users_password_warning' => 'Vul onderstaande formulier alleen in als je het wachtwoord wilt aanpassen:',
'users_system_public' => 'De eigenschappen van deze gebruiker worden voor elke gastbezoeker gebruikt. Er kan niet mee ingelogd worden en wordt automatisch toegewezen.',
'users_delete' => 'Verwijder gebruiker',
'users_delete_named' => 'Verwijder gebruiker :userName',
'users_delete_warning' => 'Dit zal de gebruiker \':userName\' volledig uit het systeem verwijderen.',
'users_delete_confirm' => 'Weet je zeker dat je deze gebruiker wilt verwijderen?',
- 'users_migrate_ownership' => 'Migrate Ownership',
- 'users_migrate_ownership_desc' => 'Select a user here if you want another user to become the owner of all items currently owned by this user.',
- 'users_none_selected' => 'No user selected',
- 'users_delete_success' => 'User successfully removed',
+ 'users_migrate_ownership' => 'Draag eigendom over',
+ 'users_migrate_ownership_desc' => 'Selecteer een gebruiker hier als u wilt dat een andere gebruiker de eigenaar wordt van alle items die momenteel eigendom zijn van deze gebruiker.',
+ 'users_none_selected' => 'Geen gebruiker geselecteerd',
+ 'users_delete_success' => 'Gebruiker succesvol verwijderd',
'users_edit' => 'Bewerk Gebruiker',
'users_edit_profile' => 'Bewerk Profiel',
'users_edit_success' => 'Gebruiker succesvol bijgewerkt',
'users_social_connected' => ':socialAccount account is succesvol aan je profiel gekoppeld.',
'users_social_disconnected' => ':socialAccount account is succesvol ontkoppeld van je profiel.',
'users_api_tokens' => 'API Tokens',
- 'users_api_tokens_none' => 'No API tokens have been created for this user',
- 'users_api_tokens_create' => 'Create Token',
- 'users_api_tokens_expires' => 'Expires',
- 'users_api_tokens_docs' => 'API Documentation',
+ 'users_api_tokens_none' => 'Er zijn geen API-tokens gemaakt voor deze gebruiker',
+ 'users_api_tokens_create' => 'Token aanmaken',
+ 'users_api_tokens_expires' => 'Verloopt',
+ 'users_api_tokens_docs' => 'API Documentatie',
// API Tokens
- 'user_api_token_create' => 'Create API Token',
+ 'user_api_token_create' => 'API-token aanmaken',
'user_api_token_name' => 'Naam',
- 'user_api_token_name_desc' => 'Give your token a readable name as a future reminder of its intended purpose.',
+ 'user_api_token_name_desc' => 'Geef je token een leesbare naam als een toekomstige herinnering aan het beoogde doel.',
'user_api_token_expiry' => 'Vervaldatum',
- 'user_api_token_expiry_desc' => 'Set a date at which this token expires. After this date, requests made using this token will no longer work. Leaving this field blank will set an expiry 100 years into the future.',
- 'user_api_token_create_secret_message' => 'Immediately after creating this token a "Token ID" & "Token Secret" will be generated and displayed. The secret will only be shown a single time so be sure to copy the value to somewhere safe and secure before proceeding.',
- 'user_api_token_create_success' => 'API token successfully created',
- 'user_api_token_update_success' => 'API token successfully updated',
+ 'user_api_token_expiry_desc' => 'Stel een datum in waarop deze token verloopt. Na deze datum zullen aanvragen die met deze token zijn ingediend niet langer werken. Als dit veld leeg blijft, wordt een vervaldatum van 100 jaar in de toekomst ingesteld.',
+ 'user_api_token_create_secret_message' => 'Onmiddellijk na het aanmaken van dit token zal een "Token ID" en "Token Geheim" worden gegenereerd en weergegeven. Het geheim zal slechts één keer getoond worden. Kopieer de waarde dus eerst op een veilige plaats voordat u doorgaat.',
+ 'user_api_token_create_success' => 'API token succesvol aangemaakt',
+ 'user_api_token_update_success' => 'API token succesvol bijgewerkt',
'user_api_token' => 'API Token',
'user_api_token_id' => 'Token ID',
- 'user_api_token_id_desc' => 'This is a non-editable system generated identifier for this token which will need to be provided in API requests.',
- 'user_api_token_secret' => 'Token Secret',
- 'user_api_token_secret_desc' => 'This is a system generated secret for this token which will need to be provided in API requests. This will only be displayed this one time so copy this value to somewhere safe and secure.',
- 'user_api_token_created' => 'Token created :timeAgo',
- 'user_api_token_updated' => 'Token updated :timeAgo',
+ 'user_api_token_id_desc' => 'Dit is een niet bewerkbaar systeem gegenereerde id voor dit token dat moet worden verstrekt in API-verzoeken.',
+ 'user_api_token_secret' => 'Geheime token sleutel',
+ 'user_api_token_secret_desc' => 'Dit is een systeem gegenereerd geheim voor dit token dat moet worden verstrekt in API verzoeken. Dit wordt maar één keer weergegeven, dus kopieër deze waarde naar een veilige plaats.',
+ 'user_api_token_created' => 'Token gemaakt :timeAgo',
+ 'user_api_token_updated' => 'Token bijgewerkt :timeAgo',
'user_api_token_delete' => 'Token Verwijderen',
- 'user_api_token_delete_warning' => 'This will fully delete this API token with the name \':tokenName\' from the system.',
- 'user_api_token_delete_confirm' => 'Are you sure you want to delete this API token?',
- 'user_api_token_delete_success' => 'API token successfully deleted',
+ 'user_api_token_delete_warning' => 'Dit zal de API-token met de naam \':tokenName\' volledig uit het systeem verwijderen.',
+ 'user_api_token_delete_confirm' => 'Weet u zeker dat u deze API-token wilt verwijderen?',
+ 'user_api_token_delete_success' => 'API-token succesvol verwijderd',
//! If editing translations files directly please ignore this in all
//! languages apart from en. Content will be auto-copied from en.
'ar' => 'العربية',
'bg' => 'Bǎlgarski',
'bs' => 'Bosanski',
- 'ca' => 'Català',
+ 'ca' => 'Catalaans',
'cs' => 'Česky',
'da' => 'Dansk',
'de' => 'Deutsch (Sie)',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'required_without' => ':attribute veld is verplicht wanneer :values niet ingesteld is.',
'required_without_all' => ':attribute veld is verplicht wanneer geen van :values ingesteld zijn.',
'same' => ':attribute en :other moeten overeenkomen.',
- 'safe_url' => 'The provided link may not be safe.',
+ 'safe_url' => 'De opgegeven link is mogelijk niet veilig.',
'size' => [
'numeric' => ':attribute moet :size zijn.',
'file' => ':attribute moet :size kilobytes zijn.',
'bookshelf_delete' => 'usunięto półkę',
'bookshelf_delete_notification' => 'Półka usunięta pomyślnie',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'skomentował',
'permissions_update' => 'zaktualizowane uprawnienia',
'remove' => 'Usuń',
'add' => 'Dodaj',
'fullscreen' => 'Pełny ekran',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Opcje sortowania',
'breadcrumb' => 'Ścieżka nawigacji',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Menu profilu',
'view_profile' => 'Zobacz profil',
'edit_profile' => 'Edytuj profil',
// Layout tabs
'tab_info' => 'Informacje',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Treść',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Jeśli masz problem z kliknięciem przycisku ":actionText", skopiuj i wklej poniższy adres URL w nowej karcie swojej przeglądarki:',
'images' => 'Obrazki',
'my_recent_drafts' => 'Moje ostatnie wersje robocze',
'my_recently_viewed' => 'Moje ostatnio wyświetlane',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Nie przeglądałeś jeszcze żadnych stron',
'no_pages_recently_created' => 'Nie utworzono ostatnio żadnych stron',
'no_pages_recently_updated' => 'Nie zaktualizowano ostatnio żadnych stron',
'404_page_not_found' => 'Strona nie została znaleziona',
'sorry_page_not_found' => 'Przepraszamy, ale strona której szukasz nie została znaleziona.',
'sorry_page_not_found_permission_warning' => 'Jeśli spodziewałeś się, że ta strona istnieje, prawdopodobnie nie masz uprawnień do jej wyświetlenia.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Powrót do strony głównej',
'error_occurred' => 'Wystąpił błąd',
'app_down' => ':appName jest aktualnie wyłączona',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'excluiu a prateleira',
'bookshelf_delete_notification' => 'Estante eliminada com sucesso',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'comentado a',
'permissions_update' => 'permissões atualizadas',
'remove' => 'Remover',
'add' => 'Adicionar',
'fullscreen' => 'Ecrã completo',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Opções de Ordenação',
'breadcrumb' => 'Caminho',
// Header
+ 'header_menu_expand' => 'Expandir Menu de Cabeçalho',
'profile_menu' => 'Menu de Perfil',
'view_profile' => 'Visualizar Perfil',
'edit_profile' => 'Editar Perfil',
// Layout tabs
'tab_info' => 'Informações',
+ 'tab_info_label' => 'Separador: Mostrar Informação Secundária',
'tab_content' => 'Conteúdo',
+ 'tab_content_label' => 'Separador: Mostrar Conteúdo Primário',
// Email Content
'email_action_help' => 'Se estiver com problemas ao carregar no botão ":actionText", copie e cole o URL abaixo no seu navegador:',
'images' => 'Imagens',
'my_recent_drafts' => 'Os Meus Rascunhos Recentes',
'my_recently_viewed' => 'Visualizados Recentemente Por Mim',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Você não viu nenhuma página',
'no_pages_recently_created' => 'Nenhuma página foi recentemente criada',
'no_pages_recently_updated' => 'Nenhuma página foi recentemente atualizada',
'404_page_not_found' => 'Página Não Encontrada',
'sorry_page_not_found' => 'Desculpe, a página que procura não foi encontrada.',
'sorry_page_not_found_permission_warning' => 'Se esperava que esta página existisse, talvez não tenha permissão para visualizá-la.',
+ 'image_not_found' => 'Imagem não encontrada',
+ 'image_not_found_subtitle' => 'Desculpe, o arquivo de imagem que estava à procura não foi encontrado.',
+ 'image_not_found_details' => 'Se estava à espera que a mesma existisse é possível que tenha sido eliminada.',
'return_home' => 'Regressar à página inicial',
'error_occurred' => 'Ocorreu um Erro',
'app_down' => ':appName está fora do ar de momento',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'excluiu a prateleira',
'bookshelf_delete_notification' => 'Prateleira excluída com sucesso',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'comentou em',
'permissions_update' => 'atualizou permissões',
'remove' => 'Remover',
'add' => 'Adicionar',
'fullscreen' => 'Tela cheia',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Opções de Ordenação',
'sort_ascending' => 'Ordenação Crescente',
'sort_descending' => 'Ordenação Decrescente',
'sort_name' => 'Nome',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Padrão',
'sort_created_at' => 'Data de Criação',
'sort_updated_at' => 'Data de Atualização',
'breadcrumb' => 'Caminho',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Menu de Perfil',
'view_profile' => 'Visualizar Perfil',
'edit_profile' => 'Editar Perfil',
// Layout tabs
'tab_info' => 'Informações',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Conteúdo',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Se você estiver tendo problemas ao clicar o botão ":actionText", copie e cole a URL abaixo no seu navegador:',
'images' => 'Imagens',
'my_recent_drafts' => 'Meus Rascunhos Recentes',
'my_recently_viewed' => 'Visualizados por mim Recentemente',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Você não visualizou nenhuma página',
'no_pages_recently_created' => 'Nenhuma página criada recentemente',
'no_pages_recently_updated' => 'Nenhuma página atualizada recentemente',
'404_page_not_found' => 'Página Não Encontrada',
'sorry_page_not_found' => 'Desculpe, a página que você está procurando não pôde ser encontrada.',
'sorry_page_not_found_permission_warning' => 'Se você esperava que esta página existisse, talvez você não tenha permissão para visualizá-la.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Retornar à página inicial',
'error_occurred' => 'Ocorreu um Erro',
'app_down' => ':appName está fora do ar no momento',
'app_homepage_select' => 'Selecione uma página',
'app_footer_links' => 'Links do Rodapé',
'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
- 'app_footer_links_label' => 'Link Label',
- 'app_footer_links_url' => 'Link URL',
- 'app_footer_links_add' => 'Add Footer Link',
+ 'app_footer_links_label' => 'Etiqueta do Link',
+ 'app_footer_links_url' => 'URL do Link',
+ 'app_footer_links_add' => 'Adicionar Link de Rodapé',
'app_disable_comments' => 'Desativar Comentários',
'app_disable_comments_toggle' => 'Desativar comentários',
'app_disable_comments_desc' => 'Desativar comentários em todas as páginas no aplicativo.<br> Comentários existentes não serão exibidos.',
'maint' => 'Manutenção',
'maint_image_cleanup' => 'Limpeza de Imagens',
'maint_image_cleanup_desc' => "Examina páginas e revisa seus conteúdos para verificar quais imagens e desenhos estão atualmente em uso e quais são redundantes. Certifique-se de criar um backup completo do banco de dados e imagens antes de executar esta ação.",
- 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions',
+ 'maint_delete_images_only_in_revisions' => 'Também excluir imagens que existem apenas em revisões de página antigas',
'maint_image_cleanup_run' => 'Executar Limpeza',
'maint_image_cleanup_warning' => ':count imagens potencialmente não utilizadas foram encontradas. Tem certeza de que deseja excluir estas imagens?',
'maint_image_cleanup_success' => ':count imagens potencialmente não utilizadas foram encontradas e excluídas!',
'recycle_bin_empty' => 'Esvaziar Lixeira',
'recycle_bin_empty_confirm' => 'Isso irá destruir permanentemente todos os itens na lixeira inclusive o conteúdo de cada item. Tem certeza de que quer esvaziar a lixeira?',
'recycle_bin_destroy_confirm' => 'Esta ação irá excluir permanentemente do sistema este item junto com todos os elementos filhos listados abaixo. Você não poderá restaurar esse conteúdo. Tem certeza de que deseja excluir permanentemente este item?',
- 'recycle_bin_destroy_list' => 'Items to be Destroyed',
- 'recycle_bin_restore_list' => 'Items to be Restored',
+ 'recycle_bin_destroy_list' => 'Itens a serem Destruídos',
+ 'recycle_bin_restore_list' => 'Itens a serem restaurados',
'recycle_bin_restore_confirm' => 'Esta ação irá restaurar o item excluído, inclusive quaisquer elementos filhos, para seu local original. Se a localização original tiver, entretanto, sido eliminada e estiver agora na lixeira, o item pai também precisará ser restaurado.',
'recycle_bin_restore_deleted_parent' => 'The parent of this item has also been deleted. These will remain deleted until that parent is also restored.',
'recycle_bin_destroy_notification' => 'Deleted :count total items from the recycle bin.',
// Audit Log
'audit' => 'Registro de auditoria',
'audit_desc' => 'This audit log displays a list of activities tracked in the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.',
- 'audit_event_filter' => 'Event Filter',
+ 'audit_event_filter' => 'Filtro de Eventos',
'audit_event_filter_no_filter' => 'Sem filtro',
'audit_deleted_item' => 'Item excluído',
'audit_deleted_item_name' => 'Nome: :name',
'user_profile' => 'Perfil do Usuário',
'users_add_new' => 'Adicionar Novo Usuário',
'users_search' => 'Pesquisar Usuários',
- 'users_latest_activity' => 'Latest Activity',
+ 'users_latest_activity' => 'Última Atividade',
'users_details' => 'Detalhes do Usuário',
'users_details_desc' => 'Defina um nome de exibição e um endereço de e-mail para este usuário. O endereço de e-mail será usado para fazer login na aplicação.',
'users_details_desc_no_email' => 'Defina um nome de exibição para este usuário para que outros usuários possam reconhecê-lo',
'users_delete_confirm' => 'Tem certeza que deseja excluir esse usuário?',
'users_migrate_ownership' => 'Migrate Ownership',
'users_migrate_ownership_desc' => 'Select a user here if you want another user to become the owner of all items currently owned by this user.',
- 'users_none_selected' => 'No user selected',
- 'users_delete_success' => 'User successfully removed',
+ 'users_none_selected' => 'Nenhum usuário selecionado',
+ 'users_delete_success' => 'Usuário removido com sucesso',
'users_edit' => 'Editar Usuário',
'users_edit_profile' => 'Editar Perfil',
'users_edit_success' => 'Usuário atualizado com sucesso',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'удалил полку',
'bookshelf_delete_notification' => 'Полка успешно удалена',
+ // Favourites
+ 'favourite_add_notification' => '":name" добавлено в избранное',
+ 'favourite_remove_notification' => ':name" удалено из избранного',
+
// Other
'commented_on' => 'прокомментировал',
'permissions_update' => 'обновил разрешения',
'remove' => 'Удалить',
'add' => 'Добавить',
'fullscreen' => 'На весь экран',
+ 'favourite' => 'Избранное',
+ 'unfavourite' => 'Убрать из избранного',
+ 'next' => 'Следующая',
+ 'previous' => 'Предыдущая',
// Sort Options
'sort_options' => 'Параметры сортировки',
'breadcrumb' => 'Навигация',
// Header
+ 'header_menu_expand' => 'Развернуть меню заголовка',
'profile_menu' => 'Меню профиля',
'view_profile' => 'Посмотреть профиль',
'edit_profile' => 'Редактировать профиль',
// Layout tabs
'tab_info' => 'Информация',
+ 'tab_info_label' => 'Вкладка: Показать вторичную информацию',
'tab_content' => 'Содержание',
+ 'tab_content_label' => 'Вкладка: Показать основной контент',
// Email Content
'email_action_help' => 'Если у вас возникли проблемы с нажатием кнопки \':actionText\', то скопируйте и вставьте указанный URL-адрес в свой браузер:',
'images' => 'Изображения',
'my_recent_drafts' => 'Мои последние черновики',
'my_recently_viewed' => 'Мои недавние просмотры',
+ 'my_most_viewed_favourites' => 'Популярное избранное',
+ 'my_favourites' => 'Мое избранное',
'no_pages_viewed' => 'Вы не просматривали ни одной страницы',
'no_pages_recently_created' => 'Нет недавно созданных страниц',
'no_pages_recently_updated' => 'Нет недавно обновленных страниц',
'404_page_not_found' => 'Страница не найдена',
'sorry_page_not_found' => 'Извините, страница, которую вы искали, не найдена.',
'sorry_page_not_found_permission_warning' => 'Если вы ожидали что страница существует, возможно у вас нет прав для её просмотра.',
+ 'image_not_found' => 'Изображение не найдено',
+ 'image_not_found_subtitle' => 'К сожалению, файл изображения, который вы искали, не найден.',
+ 'image_not_found_details' => 'Возможно данное изображение было удалено.',
'return_home' => 'вернуться на главную страницу',
'error_occurred' => 'Произошла ошибка',
'app_down' => ':appName в данный момент не доступно',
'app_homepage_desc' => 'Выберите страницу, которая будет отображаться на главной странице вместо стандартной. Права на страницы игнорируются для выбранных страниц.',
'app_homepage_select' => 'Выберите страницу',
'app_footer_links' => 'Ссылки в нижней части страницы',
- 'app_footer_links_desc' => 'Добавьте ссылки для отображения в нижнем колонтитуле сайта. Они будут отображаться внизу большинства страниц, включая те, которые не требуют входа. Вы можете использовать метку "trans::<key>" для использования системных переводов. Например: Использование "trans::common.privacy_policy" обеспечит перевод текста "Политика конфиденциальности" и "trans:common.terms_of_service" предоставит переведенный текст "Правила использования".',
+ 'app_footer_links_desc' => 'Добавьте ссылки для отображения в нижнем колонтитуле сайта. Они будут отображаться в нижней части большинства страниц, включая те, которые не требуют входа. Вы можете использовать метку "trans::<key>" для использования системных переводов. Например: Использование "trans::common.privacy_policy" обеспечит перевод текста "Политика конфиденциальности" и "trans:common.terms_of_service" предоставит переведенный текст "Правила использования".',
'app_footer_links_label' => 'Название ссылки',
'app_footer_links_url' => 'Адрес ссылки',
'app_footer_links_add' => 'Добавить ссылку',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'odstránil(a) knižnicu',
'bookshelf_delete_notification' => 'Knižnica úspešne odstránená',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'komentoval(a)',
'permissions_update' => 'aktualizované oprávnenia',
'remove' => 'Odstrániť',
'add' => 'Pridať',
'fullscreen' => 'Celá obrazovka',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Možnosti triedenia',
'breadcrumb' => 'Breadcrumb',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Menu profilu',
'view_profile' => 'Zobraziť profil',
'edit_profile' => 'Upraviť profil',
// Layout tabs
'tab_info' => 'Informácie',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Obsah',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Ak máte problém klinkúť na tlačidlo ":actionText", skopírujte a vložte URL uvedenú nižšie do Vášho prehliadača:',
'images' => 'Obrázky',
'my_recent_drafts' => 'Moje nedávne koncepty',
'my_recently_viewed' => 'Nedávno mnou zobrazené',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Nepozreli ste si žiadne stránky',
'no_pages_recently_created' => 'Žiadne stránky neboli nedávno vytvorené',
'no_pages_recently_updated' => 'Žiadne stránky neboli nedávno aktualizované',
'404_page_not_found' => 'Stránka nenájdená',
'sorry_page_not_found' => 'Prepáčte, stránka ktorú hľadáte nebola nájdená.',
'sorry_page_not_found_permission_warning' => 'If you expected this page to exist, you might not have permission to view it.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Vrátiť sa domov',
'error_occurred' => 'Nastala chyba',
'app_down' => ':appName je momentálne nedostupná',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'knjižna polica izbrisana',
'bookshelf_delete_notification' => 'Knjižna polica uspešno Izbrisana',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'komentar na',
'permissions_update' => 'pravice so posodobljene',
'remove' => 'Odstrani',
'add' => 'Dodaj',
'fullscreen' => 'Celozaslonski način',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Možnosti razvrščanja',
'breadcrumb' => 'Pot',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Meni profila',
'view_profile' => 'Ogled profila',
'edit_profile' => 'Uredi profil',
// Layout tabs
'tab_info' => 'Informacije',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Vsebina',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'V kolikor imate težave s klikom na gumb ":actionText", kopirajte in prilepite spodnjo povezavo v vaš brskalnik:',
'images' => 'Slike',
'my_recent_drafts' => 'Moji nedavni osnutki',
'my_recently_viewed' => 'Nedavno prikazano',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Niste si ogledali še nobene strani',
'no_pages_recently_created' => 'Nedavno ni bila ustvarjena nobena stran',
'no_pages_recently_updated' => 'Nedavno ni bila posodobljena nobena stran',
'404_page_not_found' => 'Strani ni mogoče najti',
'sorry_page_not_found' => 'Oprostite, strani ki jo iščete, ni mogoče najti.',
'sorry_page_not_found_permission_warning' => 'Če pričakujete, da ta stran obstaja, mogoče nimate pravic ogleda zanjo.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Vrni se domov',
'error_occurred' => 'Prišlo je do napake',
'app_down' => ':appName trenutno ni dosegljiva',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'tog bort hyllan',
'bookshelf_delete_notification' => 'Hyllan har tagits bort',
+ // Favourites
+ 'favourite_add_notification' => '":name" har lagts till i dina favoriter',
+ 'favourite_remove_notification' => '":name" har tagits bort från dina favoriter',
+
// Other
'commented_on' => 'kommenterade',
'permissions_update' => 'uppdaterade behörigheter',
'remove' => 'Radera',
'add' => 'Lägg till',
'fullscreen' => 'Helskärm',
+ 'favourite' => 'Favorit',
+ 'unfavourite' => 'Ta bort favorit',
+ 'next' => 'Nästa',
+ 'previous' => 'Föregående',
// Sort Options
'sort_options' => 'Sorteringsalternativ',
'sort_ascending' => 'Sortera stigande',
'sort_descending' => 'Sortera fallande',
'sort_name' => 'Namn',
- 'sort_default' => 'Default',
+ 'sort_default' => 'Standard',
'sort_created_at' => 'Skapad',
'sort_updated_at' => 'Uppdaterad',
'breadcrumb' => 'Brödsmula',
// Header
+ 'header_menu_expand' => 'Expandera sidhuvudsmenyn',
'profile_menu' => 'Profilmeny',
'view_profile' => 'Visa profil',
'edit_profile' => 'Redigera profil',
// Layout tabs
'tab_info' => 'Information',
+ 'tab_info_label' => 'Flik: Visa sekundär information',
'tab_content' => 'Innehåll',
+ 'tab_content_label' => 'Flik: Visa primärt innehåll',
// Email Content
'email_action_help' => 'Om du har problem, klicka på knappen ":actionText", och kopiera och klistra in den här adressen i din webbläsare:',
// Footer Link Options
// Not directly used but available for convenience to users.
- 'privacy_policy' => 'Privacy Policy',
- 'terms_of_service' => 'Terms of Service',
+ 'privacy_policy' => 'Integritetspolicy',
+ 'terms_of_service' => 'Användarvillkor',
];
'meta_created_name' => 'Skapad :timeLength av :user',
'meta_updated' => 'Uppdaterad :timeLength',
'meta_updated_name' => 'Uppdaterad :timeLength av :user',
- 'meta_owned_name' => 'Owned by :user',
+ 'meta_owned_name' => 'Ägs av :user',
'entity_select' => 'Välj enhet',
'images' => 'Bilder',
'my_recent_drafts' => 'Mina nyaste utkast',
'my_recently_viewed' => 'Mina senast visade sidor',
+ 'my_most_viewed_favourites' => 'Mina mest visade favoriter',
+ 'my_favourites' => 'Mina favoriter',
'no_pages_viewed' => 'Du har inte visat några sidor',
'no_pages_recently_created' => 'Inga sidor har skapats nyligen',
'no_pages_recently_updated' => 'Inga sidor har uppdaterats nyligen',
'permissions_intro' => 'Dessa rättigheter kommer att överskrida eventuella rollbaserade rättigheter.',
'permissions_enable' => 'Aktivera anpassade rättigheter',
'permissions_save' => 'Spara rättigheter',
- 'permissions_owner' => 'Owner',
+ 'permissions_owner' => 'Ägare',
// Search
'search_results' => 'Sökresultat',
'search_permissions_set' => 'Har anpassade rättigheter',
'search_created_by_me' => 'Skapade av mig',
'search_updated_by_me' => 'Uppdaterade av mig',
- 'search_owned_by_me' => 'Owned by me',
+ 'search_owned_by_me' => 'Ägs av mig',
'search_date_options' => 'Datumalternativ',
'search_updated_before' => 'Uppdaterade före',
'search_updated_after' => 'Uppdaterade efter',
'pages_revisions' => 'Sidrevisioner',
'pages_revisions_named' => 'Sidrevisioner för :pageName',
'pages_revision_named' => 'Sidrevision för :pageName',
- 'pages_revision_restored_from' => 'Restored from #:id; :summary',
+ 'pages_revision_restored_from' => 'Återställd från #:id; :summary',
'pages_revisions_created_by' => 'Skapad av',
'pages_revisions_date' => 'Revisionsdatum',
'pages_revisions_number' => '#',
'404_page_not_found' => 'Sidan hittades inte',
'sorry_page_not_found' => 'Tyvärr gick det inte att hitta sidan du söker.',
'sorry_page_not_found_permission_warning' => 'Om du förväntade dig att denna sida skulle existera, kanske du inte har behörighet att se den.',
+ 'image_not_found' => 'Bilden hittades inte',
+ 'image_not_found_subtitle' => 'Tyvärr gick det inte att hitta bilden du letade efter.',
+ 'image_not_found_details' => 'Om du förväntade dig att den här bilden skulle finnas kan den ha tagits bort.',
'return_home' => 'Återvänd till startsidan',
'error_occurred' => 'Ett fel inträffade',
'app_down' => ':appName är nere just nu',
'app_homepage' => 'Startsida',
'app_homepage_desc' => 'Välj en sida att använda som startsida istället för standardvyn. Den valda sidans rättigheter kommer att ignoreras.',
'app_homepage_select' => 'Välj en sida',
- 'app_footer_links' => 'Footer Links',
- 'app_footer_links_desc' => 'Add links to show within the site footer. These will be displayed at the bottom of most pages, including those that do not require login. You can use a label of "trans::<key>" to use system-defined translations. For example: Using "trans::common.privacy_policy" will provide the translated text "Privacy Policy" and "trans::common.terms_of_service" will provide the translated text "Terms of Service".',
- 'app_footer_links_label' => 'Link Label',
- 'app_footer_links_url' => 'Link URL',
- 'app_footer_links_add' => 'Add Footer Link',
+ 'app_footer_links' => 'Sidfotslänkar',
+ 'app_footer_links_desc' => 'Lägg till länkar som visas i sidfoten. Dessa kommer att visas längst ner på de flesta sidor, inklusive de som inte kräver inloggning. Du kan använda en etikett av "trans::<key>" för att använda systemdefinierade översättningar. Exempelvis översätts "trans::common.privacy_policy" till "Integritetspolicy" och "trans::common.terms_of_service" till "Användarvillkor".',
+ 'app_footer_links_label' => 'Länketikett',
+ 'app_footer_links_url' => 'Länk URL',
+ 'app_footer_links_add' => 'Lägg till sidfotslänk',
'app_disable_comments' => 'Inaktivera kommentarer',
'app_disable_comments_toggle' => 'Inaktivera kommentarer',
'app_disable_comments_desc' => 'Inaktivera kommentarer på alla sidor i applikationen. Befintliga kommentarer visas inte.',
'users_delete_named' => 'Ta bort användaren :userName',
'users_delete_warning' => 'Detta kommer att ta bort användaren \':userName\' från systemet helt och hållet.',
'users_delete_confirm' => 'Är du säker på att du vill ta bort användaren?',
- 'users_migrate_ownership' => 'Migrate Ownership',
- 'users_migrate_ownership_desc' => 'Select a user here if you want another user to become the owner of all items currently owned by this user.',
- 'users_none_selected' => 'No user selected',
- 'users_delete_success' => 'User successfully removed',
+ 'users_migrate_ownership' => 'Överför ägarskap',
+ 'users_migrate_ownership_desc' => 'Välj en användare här om du vill att en annan användare ska bli ägare till alla objekt som för närvarande ägs av denna användare.',
+ 'users_none_selected' => 'Ingen användare vald',
+ 'users_delete_success' => 'Användaren har tagits bort',
'users_edit' => 'Redigera användare',
'users_edit_profile' => 'Redigera profil',
'users_edit_success' => 'Användaren har uppdaterats',
'ar' => 'العربية',
'bg' => 'Bǎlgarski',
'bs' => 'Bosanski',
- 'ca' => 'Català',
+ 'ca' => 'Katalanska',
'cs' => 'Česky',
'da' => 'Danska',
'de' => 'Deutsch (Sie)',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'kitaplığı sildi',
'bookshelf_delete_notification' => 'Kitaplık Başarıyla Silindi',
+ // Favourites
+ 'favourite_add_notification' => '":name" favorilerinize eklendi',
+ 'favourite_remove_notification' => '":name" favorilerinizden çıkarıldı',
+
// Other
'commented_on' => 'yorum yaptı',
'permissions_update' => 'güncellenmiş izinler',
'remove' => 'Kaldır',
'add' => 'Ekle',
'fullscreen' => 'Tam Ekran',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Sıralama Seçenekleri',
'breadcrumb' => 'Gezinti Menüsü',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Profil Menüsü',
'view_profile' => 'Profili Görüntüle',
'edit_profile' => 'Profili Düzenle',
// Layout tabs
'tab_info' => 'Bilgi',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'İçerik',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => '":actionText" butonuna tıklamada sorun yaşıyorsanız, aşağıda bulunan bağlantıyı kopyalayıp tarayıcınıza yapıştırın:',
'images' => 'Görseller',
'my_recent_drafts' => 'Son Taslaklarım',
'my_recently_viewed' => 'Son Görüntülediklerim',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Herhangi bir sayfa görüntülemediniz',
'no_pages_recently_created' => 'Yakın zamanda bir sayfa oluşturulmadı',
'no_pages_recently_updated' => 'Yakın zamanda bir sayfa güncellenmedi',
'404_page_not_found' => 'Sayfa Bulunamadı',
'sorry_page_not_found' => 'Üzgünüz, aradığınız sayfa bulunamıyor.',
'sorry_page_not_found_permission_warning' => 'Bu sayfanın var olduğunu düşünüyorsanız, görüntüleme iznine sahip olmayabilirsiniz.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Ana sayfaya dön',
'error_occurred' => 'Bir Hata Oluştu',
'app_down' => ':appName şu anda erişilemez durumda',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'İbranice',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'видалив книжкову полицю',
'bookshelf_delete_notification' => 'Книжкову полицю успішно видалено',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'прокоментував',
'permissions_update' => 'оновив дозволи',
'remove' => 'Видалити',
'add' => 'Додати',
'fullscreen' => 'На весь екран',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Параметри сортування',
'breadcrumb' => 'Навігація',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Меню профілю',
'view_profile' => 'Переглянути профіль',
'edit_profile' => 'Редагувати профіль',
// Layout tabs
'tab_info' => 'Інфо',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Вміст',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Якщо у вас виникають проблеми при натисканні кнопки ":actionText", скопіюйте та вставте URL у свій веб-браузер:',
'images' => 'Зображення',
'my_recent_drafts' => 'Мої останні чернетки',
'my_recently_viewed' => 'Мої недавні перегляди',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Ви не переглядали жодної сторінки',
'no_pages_recently_created' => 'Не було створено жодної сторінки',
'no_pages_recently_updated' => 'Немає недавно оновлених сторінок',
'404_page_not_found' => 'Сторінку не знайдено',
'sorry_page_not_found' => 'Вибачте, сторінку, яку ви шукали, не знайдено.',
'sorry_page_not_found_permission_warning' => 'Якщо ви очікували що ця сторінки існує – можливо у вас немає дозволу на її перегляд.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Повернутися на головну',
'error_occurred' => 'Виникла помилка',
'app_down' => ':appName зараз недоступний',
'ar' => 'العربية',
'bg' => 'Bǎlgarski',
'bs' => 'Bosanski',
- 'ca' => 'Каталаньський',
+ 'ca' => 'Català',
'cs' => 'Česky',
'da' => 'Dansk',
'de' => 'Deutsch (Sie)',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => 'đã xóa giá sách',
'bookshelf_delete_notification' => 'Giá sách đã được xóa thành công',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => 'đã bình luận về',
'permissions_update' => 'các quyền đã được cập nhật',
'remove' => 'Xóa bỏ',
'add' => 'Thêm',
'fullscreen' => 'Toàn màn hình',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => 'Tùy Chọn Sắp Xếp',
'breadcrumb' => 'Đường dẫn liên kết',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => 'Menu Hồ sơ',
'view_profile' => 'Xem Hồ sơ',
'edit_profile' => 'Sửa Hồ sơ',
// Layout tabs
'tab_info' => 'Thông tin',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => 'Nội dung',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => 'Nếu bạn đang có vấn đề trong việc bấm nút ":actionText", sao chép và dán địa chỉ URL dưới đây vào trình duyệt web:',
'images' => 'Ảnh',
'my_recent_drafts' => 'Bản nháp gần đây của tôi',
'my_recently_viewed' => 'Xem gần đây',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => 'Bạn chưa xem bất cứ trang nào',
'no_pages_recently_created' => 'Không có trang nào được tạo gần đây',
'no_pages_recently_updated' => 'Không có trang nào được cập nhật gần đây',
'404_page_not_found' => 'Không Tìm Thấy Trang',
'sorry_page_not_found' => 'Xin lỗi, Không tìm thấy trang bạn đang tìm kiếm.',
'sorry_page_not_found_permission_warning' => 'Nếu trang bạn tìm kiếm tồn tại, có thể bạn đang không có quyền truy cập.',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => 'Quay lại trang chủ',
'error_occurred' => 'Đã xảy ra lỗi',
'app_down' => ':appName hiện đang ngoại tuyến',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => '删除了书架',
'bookshelf_delete_notification' => '书架已成功删除',
+ // Favourites
+ 'favourite_add_notification' => '":name" 已添加到你的收藏',
+ 'favourite_remove_notification' => '":name" 已从你的收藏中删除',
+
// Other
'commented_on' => '评论',
'permissions_update' => '权限已更新',
'sign_up' => '注册',
'log_in' => '登录',
'log_in_with' => '以:socialDriver登录',
- 'sign_up_with' => '注册:socialDriver',
+ 'sign_up_with' => '通过 :socialDriver 账号登录',
'logout' => '注销',
- 'name' => 'å§\93å\90\8d',
+ 'name' => 'å\90\8dç§°',
'username' => '用户名',
'email' => 'Email地址',
'password' => '密码',
'ldap_email_hint' => '请输入用于此帐户的电子邮件。',
'create_account' => '创建账户',
'already_have_account' => '您已经有账号?',
- 'dont_have_account' => 'æ\82¨è¿\98没注å\86\8c?',
+ 'dont_have_account' => 'æ\82¨è¿\98没æ\9c\89è´¦å\8f·å\90\97?',
'social_login' => 'SNS登录',
- 'social_registration' => 'SNS注册',
- 'social_registration_text' => '其他服务注册/登录。',
+ 'social_registration' => '使用社交网站账号注册',
+ 'social_registration_text' => '使用其他服务注册并登录。',
'register_thanks' => '注册完成!',
'register_confirm' => '请点击查收您的Email,并点击确认。',
'remove' => '删除',
'add' => '添加',
'fullscreen' => '全屏',
+ 'favourite' => '收藏',
+ 'unfavourite' => '不喜欢',
+ 'next' => '下一页',
+ 'previous' => '上一页',
// Sort Options
'sort_options' => '排序选项',
'breadcrumb' => '面包屑导航',
// Header
+ 'header_menu_expand' => '展开标头菜单',
'profile_menu' => '个人资料',
'view_profile' => '查看资料',
'edit_profile' => '编辑资料',
// Layout tabs
'tab_info' => '信息',
+ 'tab_info_label' => '标签:显示次要信息',
'tab_content' => '内容',
+ 'tab_content_label' => '标签:显示主要内容',
// Email Content
'email_action_help' => '如果您无法点击“:actionText”按钮,请将下面的网址复制到您的浏览器中打开:',
'images' => '图片',
'my_recent_drafts' => '我最近的草稿',
'my_recently_viewed' => '我最近看过',
+ 'my_most_viewed_favourites' => '我浏览最多的收藏',
+ 'my_favourites' => '我的收藏',
'no_pages_viewed' => '您尚未查看任何页面',
'no_pages_recently_created' => '最近没有页面被创建',
'no_pages_recently_updated' => '最近没有页面被更新',
'404_page_not_found' => '无法找到页面',
'sorry_page_not_found' => '对不起,无法找到您想访问的页面。',
'sorry_page_not_found_permission_warning' => '您可能没有查看权限。',
+ 'image_not_found' => '未找到图片',
+ 'image_not_found_subtitle' => '对不起,无法找到您想访问的图片。',
+ 'image_not_found_details' => '原本放在这里的图片已被删除。',
'return_home' => '返回主页',
'error_occurred' => '出现错误',
'app_down' => ':appName现在正在关闭',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => 'עברית',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
'bookshelf_delete' => '已刪除書架',
'bookshelf_delete_notification' => '書架已刪除成功',
+ // Favourites
+ 'favourite_add_notification' => '":name" has been added to your favourites',
+ 'favourite_remove_notification' => '":name" has been removed from your favourites',
+
// Other
'commented_on' => '評論',
'permissions_update' => '更新權限',
'remove' => '移除',
'add' => '新增',
'fullscreen' => '全螢幕',
+ 'favourite' => 'Favourite',
+ 'unfavourite' => 'Unfavourite',
+ 'next' => 'Next',
+ 'previous' => 'Previous',
// Sort Options
'sort_options' => '排序選項',
'breadcrumb' => '頁面路徑',
// Header
+ 'header_menu_expand' => 'Expand Header Menu',
'profile_menu' => '個人資料選單',
'view_profile' => '檢視個人資料',
'edit_profile' => '編輯個人資料',
// Layout tabs
'tab_info' => '資訊',
+ 'tab_info_label' => 'Tab: Show Secondary Information',
'tab_content' => '內容',
+ 'tab_content_label' => 'Tab: Show Primary Content',
// Email Content
'email_action_help' => '如果您無法點擊 ":actionText" 按鈕,請將下方的網址複製並貼上到您的網路瀏覽器中:',
'images' => '圖片',
'my_recent_drafts' => '我最近的草稿',
'my_recently_viewed' => '我最近檢視',
+ 'my_most_viewed_favourites' => 'My Most Viewed Favourites',
+ 'my_favourites' => 'My Favourites',
'no_pages_viewed' => '您尚未看過任何頁面',
'no_pages_recently_created' => '最近未建立任何頁面',
'no_pages_recently_updated' => '最近沒有頁面被更新',
'404_page_not_found' => '找不到頁面',
'sorry_page_not_found' => '抱歉,找不到您在尋找的頁面。',
'sorry_page_not_found_permission_warning' => '如果您確認這個頁面存在,則代表可能沒有查看它的權限。',
+ 'image_not_found' => 'Image Not Found',
+ 'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.',
+ 'image_not_found_details' => 'If you expected this image to exist it might have been deleted.',
'return_home' => '回到首頁',
'error_occurred' => '發生錯誤',
'app_down' => ':appName 離線中',
'es_AR' => 'Español Argentina',
'fr' => 'Français',
'he' => '希伯來語',
+ 'hr' => 'Hrvatski',
'hu' => 'Magyar',
'id' => 'Bahasa Indonesia',
'it' => 'Italian',
padding: $-m $-xxl;
margin-inline-start: auto;
margin-inline-end: auto;
- margin-bottom: $-xl;
+ margin-bottom: $-l;
overflow: initial;
min-height: 60vh;
&.auto-height {
}
}
+.outline-hover {
+ border: 1px solid transparent !important;
+ &:hover {
+ border: 1px solid rgba(0, 0, 0, 0.1) !important;
+ }
+}
+
+.fade-in-when-active {
+ opacity: 0.6;
+ transition: opacity ease-in-out 120ms;
+ &:hover, &:focus-within {
+ opacity: 1;
+ }
+}
+
/**
* Tags
*/
margin-bottom: $-xs;
margin-inline-end: $-xs;
border-radius: 4px;
- border: 1px solid #CCC;
+ border: 1px solid;
overflow: hidden;
font-size: 0.85em;
- a, a:hover, a:active {
+ @include lightDark(border-color, #CCC, #666);
+ a, span, a:hover, a:active {
padding: 4px 8px;
- @include lightDark(color, #777, #999);
+ @include lightDark(color, rgba(0, 0, 0, 0.6), rgba(255, 255, 255, 0.8));
transition: background-color ease-in-out 80ms;
text-decoration: none;
}
@include lightDark(background-color, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.3));
}
svg {
- fill: #888;
+ @include lightDark(fill, rgba(0, 0, 0, 0.5), rgba(255, 255, 255, 0.5));
}
.tag-value {
- border-inline-start: 1px solid #DDD;
+ border-inline-start: 1px solid;
+ @include lightDark(border-color, #DDD, #666);
@include lightDark(background-color, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.2))
}
}
align-items: center;
padding: $-s $-m;
padding-bottom: ($-s - 2px);
+ width: 100%;
svg {
display: inline-block;
width: 24px;
float: left;
margin: 0;
cursor: pointer;
- width: (100%/6);
+ width: math.div(100%, 6);
height: auto;
@include lightDark(border-color, #ddd, #000);
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
}
}
@include smaller-than($xl) {
- width: (100%/4);
+ width: math.div(100%, 4);
}
@include smaller-than($m) {
.image-meta {
max-width: 100%;
td {
overflow: hidden;
- padding: $-xxs/2 0;
+ padding: math.div($-xxs, 2) 0;
}
}
@extend .input-base;
}
+select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%23666666'><polygon points='0,0 100,0 50,50'/></svg>");
+ background-size: 12px;
+ background-position: calc(100% - 20px) 70%;
+ background-repeat: no-repeat;
+}
+
input[type=date] {
width: 190px;
}
@include lightDark(color, #000, #fff);
text-decoration: none;
}
+ &:focus {
+ @include lightDark(background-color, #eee, #333);
+ outline-color: var(--color-primary);
+ color: var(--color-primary);
+ }
}
header .dropdown-container {
display: block;
z-index: 5;
background-color: #FFF;
border-bottom: 1px solid #DDD;
+ @include lightDark(border-bottom-color, #DDD, #333);
box-shadow: $bs-card;
}
.tri-layout-mobile-tab {
text-align: center;
border-bottom: 3px solid #BBB;
cursor: pointer;
+ margin: 0;
+ @include lightDark(background-color, #FFF, #222);
+ @include lightDark(border-bottom-color, #BBB, #333);
&:first-child {
border-inline-end: 1px solid #DDD;
+ @include lightDark(border-inline-end-color, #DDD, #000);
}
- &.active {
- border-bottom-color: currentColor;
+ &[aria-selected="true"] {
+ border-bottom-color: currentColor !important;
}
}
.justify-center {
justify-content: center;
}
+.justify-space-between {
+ justify-content: space-between;
+}
.items-center {
align-items: center;
}
}
}
+/**
+ * Border radiuses
+ */
+.rounded {
+ border-radius: 4px;
+}
+
/**
* Inline content columns
*/
margin-inline-start: 0;
margin-inline-end: 0;
}
-}
+}
\ No newline at end of file
background-color: rgba(0, 0, 0, 0.1);
border-radius: 4px;
}
- &.outline-hover {
- border: 1px solid transparent;
- }
&.outline-hover:hover {
background-color: transparent;
- border-color: rgba(0, 0, 0, 0.1);
}
&:focus {
@include lightDark(background-color, #eee, #222);
}
}
+.entity-item-tags {
+ font-size: .75rem;
+ opacity: 1;
+ .primary-background-light {
+ background: transparent;
+ }
+ .tag-name {
+ background-color: rgba(0, 0, 0, 0.05);
+ }
+}
+
.dropdown-container {
display: inline-block;
vertical-align: top;
border: 1px solid #DDD;
overflow: auto;
line-height: 1.2;
+ word-break: break-word;
}
td p, th p {
margin: 0;
}
}
+a.no-link-style {
+ color: inherit;
+ &:hover {
+ text-decoration: none;
+ }
+}
+
.blended-links a {
color: inherit;
svg {
&.faded {
background-image: linear-gradient(to right, #FFF, #e3e0e0 20%, #e3e0e0 80%, #FFF);
}
+ &.darker {
+ @include lightDark(background, #DDD, #666);
+ }
&.margin-top, &.even {
margin-top: $-l;
}
+@use "sass:math";
@import "variables";
@import "mixins";
-@import "spacing";
@import "html";
@import "text";
@import "layout";
@import "blocks";
@import "tables";
-@import "header";
@import "lists";
@import "pages";
-
html, body {
background-color: #FFF;
}
}
pre code {
white-space: pre-wrap;
+}
+
+.page-break {
+ page-break-after: always;
+}
+@media screen {
+ .page-break {
+ border-top: 1px solid #DDD;
+ }
+}
+
+ul.contents ul li {
+ list-style: circle;
+}
+
+.chapter-hint {
+ color: #888;
+ margin-top: 32px;
+}
+.chapter-hint + h1 {
+ margin-top: 0;
}
\ No newline at end of file
+@use "sass:math";
@import "variables";
header {
+@use "sass:math";
+
@import "reset";
@import "variables";
@import "mixins";
color: #FFF;
fill: #FFF;
svg {
- width: $btt-size / 1.5;
- height: $btt-size / 1.5;
+ width: math.div($btt-size, 1.5);
+ height: math.div($btt-size, 1.5);
margin-inline-end: 4px;
}
width: $btt-size;
}
}
+.skip-to-content-link {
+ position: fixed;
+ top: -$-xxl;
+ left: 0;
+ background-color: #FFF;
+ z-index: 15;
+ border-radius: 0 4px 4px 0;
+ display: block;
+ box-shadow: $bs-dark;
+ font-weight: bold;
+ &:focus {
+ top: $-xl;
+ outline-offset: -10px;
+ outline: 2px dotted var(--color-primary);
+ }
+}
+
.contained-search-box {
display: flex;
height: 38px;
<h5 id="{{ $endpoint['name'] }}" class="text-mono mb-m">
<span class="api-method" data-method="{{ $endpoint['method'] }}">{{ $endpoint['method'] }}</span>
@if($endpoint['controller_method_kebab'] === 'list')
- <a style="color: inherit;" target="_blank" href="{{ url($endpoint['uri']) }}">{{ url($endpoint['uri']) }}</a>
+ <a style="color: inherit;" target="_blank" rel="noopener" href="{{ url($endpoint['uri']) }}">{{ url($endpoint['uri']) }}</a>
@else
{{ url($endpoint['uri']) }}
@endif
-@foreach($attachments as $attachment)
- <div class="attachment icon-list">
- <a class="icon-list-item py-xs" href="{{ $attachment->getUrl() }}" @if($attachment->external) target="_blank" @endif>
- <span class="icon">@icon($attachment->external ? 'export' : 'file')</span>
- <span>{{ $attachment->name }}</span>
- </a>
- </div>
-@endforeach
\ No newline at end of file
+<div component="attachments-list">
+ @foreach($attachments as $attachment)
+ <div class="attachment icon-list">
+ <a class="icon-list-item py-xs attachment-{{ $attachment->external ? 'link' : 'file' }}" href="{{ $attachment->getUrl() }}" @if($attachment->external) target="_blank" @endif>
+ <span class="icon">@icon($attachment->external ? 'export' : 'file')</span>
+ <span>{{ $attachment->name }}</span>
+ </a>
+ </div>
+ @endforeach
+</div>
\ No newline at end of file
class="card drag-card">
<div class="handle">@icon('grip')</div>
<div class="py-s">
- <a href="{{ $attachment->getUrl() }}" target="_blank">{{ $attachment->name }}</a>
+ <a href="{{ $attachment->getUrl() }}" target="_blank" rel="noopener">{{ $attachment->name }}</a>
</div>
<div class="flex-fill justify-flex-end">
<button component="event-emit-select"
{!! csrf_field() !!}
<div>
- <button id="saml-login" class="button outline block svg">
+ <button id="saml-login" class="button outline svg">
@icon('saml2')
<span>{{ trans('auth.log_in_with', ['socialDriver' => config('saml2.name')]) }}</span>
</button>
<meta name="base-url" content="{{ url('/') }}">
<meta charset="utf-8">
+ <!-- Social Cards Meta -->
+ <meta property="og:title" content="{{ isset($pageTitle) ? $pageTitle . ' | ' : '' }}{{ setting('app-name') }}">
+ <meta property="og:url" content="{{ url()->current() }}">
+ @stack('social-meta')
+
+
<!-- Styles and Fonts -->
<link rel="stylesheet" href="{{ versioned_asset('dist/styles.css') }}">
<link rel="stylesheet" media="print" href="{{ versioned_asset('dist/print-styles.css') }}">
</head>
<body class="@yield('body-class')">
+ @include('common.parts.skip-to-content')
@include('partials.notifications')
@include('common.header')
- <div id="content" class="block">
+ <div id="content" components="@yield('content-components')" class="block">
@yield('content')
</div>
-<!doctype html>
-<html lang="{{ config('app.lang') }}">
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <title>{{ $book->name }}</title>
+@extends('export-layout')
- @include('partials.export-styles', ['format' => $format])
-
- <style>
- .page-break {
- page-break-after: always;
- }
- .chapter-hint {
- color: #888;
- margin-top: 32px;
- }
- .chapter-hint + h1 {
- margin-top: 0;
- }
- ul.contents ul li {
- list-style: circle;
- }
- @media screen {
- .page-break {
- border-top: 1px solid #DDD;
- }
- }
- </style>
- @yield('head')
- @include('partials.custom-head')
-</head>
-<body>
-
-<div class="page-content">
+@section('title', $book->name)
+@section('content')
<h1 style="font-size: 4.8em">{{$book->name}}</h1>
<p>{{ $book->description }}</p>
@endif
@endforeach
-
-</div>
-
-</body>
-</html>
+@endsection
\ No newline at end of file
{{ csrf_field() }}
<div class="form-group title-input">
<label for="name">{{ trans('common.name') }}</label>
- @include('form.text', ['name' => 'name'])
+ @include('form.text', ['name' => 'name', 'autofocus' => true])
</div>
<div class="form-group description-input">
option:entity-search:entity-type="book"
@stop
+@push('social-meta')
+ <meta property="og:description" content="{{ Str::limit($book->description, 100, '...') }}">
+ @if($book->cover)
+ <meta property="og:image" content="{{ $book->getBookCover() }}">
+ @endif
+@endpush
+
@section('body')
<div class="mb-s">
<hr class="primary-background">
+ @if(signedInUser())
+ @include('partials.entity-favourite-action', ['entity' => $book])
+ @endif
@include('partials.entity-export-menu', ['entity' => $book])
</div>
</div>
-<!doctype html>
-<html lang="{{ config('app.lang') }}">
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <title>{{ $chapter->name }}</title>
+@extends('export-layout')
- @include('partials.export-styles', ['format' => $format])
-
- <style>
- .page-break {
- page-break-after: always;
- }
- ul.contents ul li {
- list-style: circle;
- }
- @media screen {
- .page-break {
- border-top: 1px solid #DDD;
- }
- }
- </style>
- @include('partials.custom-head')
-</head>
-<body>
-
-<div class="page-content">
+@section('title', $chapter->name)
+@section('content')
<h1 style="font-size: 4.8em">{{$chapter->name}}</h1>
<p>{{ $chapter->description }}</p>
<h1 id="page-{{$page->id}}">{{ $page->name }}</h1>
{!! $page->html !!}
@endforeach
-
-</div>
-
-</body>
-</html>
+@endsection
\ No newline at end of file
<div class="form-group title-input">
<label for="name">{{ trans('common.name') }}</label>
- @include('form.text', ['name' => 'name'])
+ @include('form.text', ['name' => 'name', 'autofocus' => true])
</div>
<div class="form-group description-input">
option:entity-search:entity-type="chapter"
@stop
+@push('social-meta')
+ <meta property="og:description" content="{{ Str::limit($chapter->description, 100, '...') }}">
+@endpush
+
@section('body')
<div class="mb-m print-hidden">
@include('partials.entity-search-results')
</main>
+ @include('partials.entity-sibling-navigation', ['next' => $next, 'previous' => $previous])
+
@stop
@section('right')
<hr class="primary-background"/>
+ @if(signedInUser())
+ @include('partials.entity-favourite-action', ['entity' => $chapter])
+ @endif
@include('partials.entity-export-menu', ['entity' => $chapter])
</div>
</div>
<h1 class="list-heading">{{ $title }}</h1>
<div class="book-contents">
- @include('partials.entity-list', ['entities' => $pages, 'style' => 'detailed'])
+ @include('partials.entity-list', ['entities' => $entities, 'style' => 'detailed'])
</div>
<div class="text-center">
- {!! $pages->links() !!}
+ {!! $entities->links() !!}
</div>
</main>
</div>
--- /dev/null
+@extends('simple-layout')
+
+@section('body')
+ <div class="container small pt-xl">
+ <main class="card content-wrap">
+ <h1 class="list-heading">{{ $title }}</h1>
+
+ <div class="book-contents">
+ @include('partials.entity-list', ['entities' => $entities, 'style' => 'detailed'])
+ </div>
+
+ <div class="text-right">
+ @if($hasMoreLink)
+ <a href="{{ $hasMoreLink }}" class="button outline">{{ trans('common.more') }}</a>
+ @endif
+ </div>
+ </main>
+ </div>
+@stop
\ No newline at end of file
@if(count(setting('app-footer-links', [])) > 0)
<footer>
@foreach(setting('app-footer-links', []) as $link)
- <a href="{{ $link['url'] }}" target="_blank">{{ strpos($link['label'], 'trans::') === 0 ? trans(str_replace('trans::', '', $link['label'])) : $link['label'] }}</a>
+ <a href="{{ $link['url'] }}" target="_blank" rel="noopener">{{ strpos($link['label'], 'trans::') === 0 ? trans(str_replace('trans::', '', $link['label'])) : $link['label'] }}</a>
@endforeach
</footer>
@endif
\ No newline at end of file
-<header id="header" header-mobile-toggle class="primary-background">
+<header id="header" component="header-mobile-toggle" class="primary-background">
<div class="grid mx-l">
<div>
<span class="logo-text">{{ setting('app-name') }}</span>
@endif
</a>
- <div class="mobile-menu-toggle hide-over-l">@icon('more')</div>
+ <button type="button"
+ refs="header-mobile-toggle@toggle"
+ title="{{ trans('common.header_menu_expand') }}"
+ aria-expanded="false"
+ class="mobile-menu-toggle hide-over-l">@icon('more')</button>
</div>
<div class="flex-container-row justify-center hide-under-l">
</div>
<div class="text-right">
- <nav class="header-links">
+ <nav refs="header-mobile-toggle@menu" class="header-links">
<div class="links text-center">
@if (hasAppAccess())
<a class="hide-over-l" href="{{ url('/search') }}">@icon('search'){{ trans('common.search') }}</a>
</div>
@if(signedInUser())
<?php $currentUser = user(); ?>
- <div class="dropdown-container" component="dropdown">
+ <div class="dropdown-container" component="dropdown" option:dropdown:bubble-escapes="true">
<span class="user-name py-s hide-under-l" refs="dropdown@toggle"
aria-haspopup="true" aria-expanded="false" aria-label="{{ trans('common.profile_menu') }}" tabindex="0">
<img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}">
<span class="name">{{ $currentUser->getShortName(9) }}</span> @icon('caret-down')
</span>
<ul refs="dropdown@menu" class="dropdown-menu" role="menu">
+ <li>
+ <a href="{{ url('/favourites') }}">@icon('star'){{ trans('entities.my_favourites') }}</a>
+ </li>
<li>
<a href="{{ $currentUser->getProfileUrl() }}">@icon('user'){{ trans('common.view_profile') }}</a>
</li>
</a>
@endif
@include('partials.view-toggle', ['view' => $view, 'type' => 'books'])
- @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
- @include('partials.dark-mode-toggle', ['classes' => 'text-muted icon-list-item text-primary'])
+ @include('components.expand-toggle', ['classes' => 'text-primary', 'target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
+ @include('partials.dark-mode-toggle', ['classes' => 'icon-list-item text-primary'])
</div>
</div>
@stop
<div class="actions mb-xl">
<h5>{{ trans('common.actions') }}</h5>
<div class="icon-list text-primary">
- @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
- @include('partials.dark-mode-toggle', ['classes' => 'text-muted icon-list-item text-primary'])
+ @include('components.expand-toggle', ['classes' => 'text-primary', 'target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
+ @include('partials.dark-mode-toggle', ['classes' => 'icon-list-item text-primary'])
</div>
</div>
@stop
\ No newline at end of file
</a>
@endif
@include('partials.view-toggle', ['view' => $view, 'type' => 'shelves'])
- @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
- @include('partials.dark-mode-toggle', ['classes' => 'text-muted icon-list-item text-primary'])
+ @include('components.expand-toggle', ['classes' => 'text-primary', 'target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
+ @include('partials.dark-mode-toggle', ['classes' => 'icon-list-item text-primary'])
</div>
</div>
@stop
</div>
@endif
+@if(count($favourites) > 0)
+ <div id="top-favourites" class="mb-xl">
+ <h5>
+ <a href="{{ url('/favourites') }}" class="no-color">{{ trans('entities.my_most_viewed_favourites') }}</a>
+ </h5>
+ @include('partials.entity-list', [
+ 'entities' => $favourites,
+ 'style' => 'compact',
+ ])
+ </div>
+@endif
+
<div class="mb-xl">
<h5>{{ trans('entities.' . (auth()->check() ? 'my_recently_viewed' : 'books_recent')) }}</h5>
@include('partials.entity-list', [
<div class="grid half">
<div>
<div class="icon-list inline block">
- @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
+ @include('components.expand-toggle', ['classes' => 'text-muted text-primary', 'target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
</div>
</div>
<div class="text-m-right">
</div>
<div>
+ @if(count($favourites) > 0)
+ <div id="top-favourites" class="card mb-xl">
+ <h3 class="card-title">
+ <a href="{{ url('/favourites') }}" class="no-color">{{ trans('entities.my_most_viewed_favourites') }}</a>
+ </h3>
+ <div class="px-m">
+ @include('partials.entity-list', [
+ 'entities' => $favourites,
+ 'style' => 'compact',
+ ])
+ </div>
+ </div>
+ @endif
+
<div id="recent-pages" class="card mb-xl">
<h3 class="card-title"><a class="no-color" href="{{ url("/pages/recently-updated") }}">{{ trans('entities.recently_updated_pages') }}</a></h3>
<div id="recently-updated-pages" class="px-m">
--- /dev/null
+<a class="px-m py-s skip-to-content-link" href="#main-content">{{ trans('common.skip_to_main_content') }}</a>
\ No newline at end of file
<button type="button" expand-toggle="{{ $target }}"
expand-toggle-update-endpoint="{{ url('/settings/users/'. user()->id .'/update-expansion-preference/' . $key) }}"
expand-toggle-is-open="{{ $isOpen ? 'yes' : 'no' }}"
- class="text-muted icon-list-item text-primary">
+ class="icon-list-item {{ $classes ?? '' }}">
<span>@icon('expand-text')</span>
<span>{{ trans('common.toggle_details') }}</span>
</button>
option:ajax-form:url="{{ url('images/' . $image->id) }}">
<div class="image-manager-viewer">
- <a href="{{ $image->url }}" target="_blank" class="block">
+ <a href="{{ $image->url }}" target="_blank" rel="noopener" class="block">
<img src="{{ $image->thumbs['display'] }}"
alt="{{ $image->name }}"
class="anim fadeIn"
<li>
<a href="{{ $page->url }}"
target="_blank"
+ rel="noopener"
class="text-neg">{{ $page->name }}</a>
</li>
@endforeach
<div page-picker>
<div class="input-base">
<span @if($value) style="display: none" @endif page-picker-default class="text-muted italic">{{ $placeholder }}</span>
- <a @if(!$value) style="display: none" @endif href="{{ url('/link/' . $value) }}" target="_blank" class="text-page" page-picker-display>#{{$value}}, {{$value ? \BookStack\Entities\Models\Page::find($value)->name : '' }}</a>
+ <a @if(!$value) style="display: none" @endif href="{{ url('/link/' . $value) }}" target="_blank" rel="noopener" class="text-page" page-picker-display>#{{$value}}, {{$value ? \BookStack\Entities\Models\Page::find($value)->name : '' }}</a>
</div>
<br>
<input type="hidden" value="{{$value}}" name="{{$name}}" id="{{$name}}">
@foreach($entity->tags as $tag)
<div class="tag-item primary-background-light">
- <div class="tag-name"><a href="{{ url('/search?term=%5B' . urlencode($tag->name) .'%5D') }}">@icon('tag'){{ $tag->name }}</a></div>
- @if($tag->value) <div class="tag-value"><a href="{{ url('/search?term=%5B' . urlencode($tag->name) .'%3D' . urlencode($tag->value) . '%5D') }}">{{$tag->value}}</a></div> @endif
+ @if($linked ?? true)
+ <div class="tag-name"><a href="{{ $tag->nameUrl() }}">@icon('tag'){{ $tag->name }}</a></div>
+ @if($tag->value) <div class="tag-value"><a href="{{ $tag->valueUrl() }}">{{$tag->value}}</a></div> @endif
+ @else
+ <div class="tag-name"><span>@icon('tag'){{ $tag->name }}</span></div>
+ @if($tag->value) <div class="tag-value"><span>{{$tag->value}}</span></div> @endif
+ @endif
</div>
@endforeach
\ No newline at end of file
<div class="card mb-xl px-l pb-l pt-l">
<div class="grid half v-center">
<div>
- <h1 class="list-heading">{{ $message ?? trans('errors.404_page_not_found') }}</h1>
- <h5>{{ trans('errors.sorry_page_not_found') }}</h5>
- <p>{{ trans('errors.sorry_page_not_found_permission_warning') }}</p>
+ @include('errors.parts.not-found-text', [
+ 'title' => $message ?? trans('errors.404_page_not_found'),
+ 'subtitle' => $subtitle ?? trans('errors.sorry_page_not_found'),
+ 'details' => $details ?? trans('errors.sorry_page_not_found_permission_warning'),
+ ])
</div>
<div class="text-right">
@if(!signedInUser())
<div class="card mb-xl">
<h3 class="card-title">{{ trans('entities.pages_popular') }}</h3>
<div class="px-m">
- @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, ['page']), 'style' => 'compact'])
+ @include('partials.entity-list', ['entities' => (new \BookStack\Entities\Queries\Popular)->run(10, 0, ['page']), 'style' => 'compact'])
</div>
</div>
</div>
<div class="card mb-xl">
<h3 class="card-title">{{ trans('entities.books_popular') }}</h3>
<div class="px-m">
- @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, ['book']), 'style' => 'compact'])
+ @include('partials.entity-list', ['entities' => (new \BookStack\Entities\Queries\Popular)->run(10, 0, ['book']), 'style' => 'compact'])
</div>
</div>
</div>
<div class="card mb-xl">
<h3 class="card-title">{{ trans('entities.chapters_popular') }}</h3>
<div class="px-m">
- @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, ['chapter']), 'style' => 'compact'])
+ @include('partials.entity-list', ['entities' => (new \BookStack\Entities\Queries\Popular)->run(10, 0, ['chapter']), 'style' => 'compact'])
</div>
</div>
</div>
<div class="container small py-xl">
<main class="card content-wrap auto-height">
- <div class="body">
+ <div id="main-content" class="body">
<h3>{{ trans('errors.error_occurred') }}</h3>
<h5 class="mb-m">{{ $message ?? 'An unknown error occurred' }}</h5>
<p><a href="{{ url('/') }}" class="button outline">{{ trans('errors.return_home') }}</a></p>
--- /dev/null
+{{--The below text may be dynamic based upon language and scenario.--}}
+{{--It's safer to add new text sections here rather than altering existing ones.--}}
+<h1 class="list-heading">{{ $title }}</h1>
+<h5>{{ $subtitle }}</h5>
+<p>{{ $details }}</p>
\ No newline at end of file
--- /dev/null
+<!doctype html>
+<html lang="{{ config('app.lang') }}">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>@yield('title')</title>
+
+ @include('partials.export-styles', ['format' => $format])
+ @include('partials.export-custom-head')
+</head>
+<body>
+<div class="page-content">
+ @yield('content')
+</div>
+</body>
+</html>
\ No newline at end of file
<table permissions-table class="table permissions-table toggle-switch-list" style="{{ !$model->restricted ? 'display: none' : '' }}">
<tr>
<th>{{ trans('common.role') }}</th>
- <th @if($model->isA('page')) colspan="3" @else colspan="4" @endif>
+ <th colspan="{{ $model->isA('page') ? '3' : '4' }}">
{{ trans('common.actions') }}
<a href="#" permissions-table-toggle-all class="text-small ml-m text-primary">{{ trans('common.toggle_all') }}</a>
</th>
@section('content')
- <div class="flex-fill flex fill-height">
+ <div id="main-content" class="flex-fill flex fill-height">
<form action="{{ $page->getUrl() }}" autocomplete="off" data-page-id="{{ $page->id }}" method="POST" class="flex flex-fill">
{{ csrf_field() }}
-<!doctype html>
-<html lang="{{ config('app.lang') }}">
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <title>{{ $page->name }}</title>
+@extends('export-layout')
- @include('partials.export-styles', ['format' => $format])
+@section('title', $page->name)
- @if($format === 'pdf')
- <style>
- body {
- font-size: 14px;
- line-height: 1.2;
- }
+@section('content')
+ @include('pages.page-display')
- h1, h2, h3, h4, h5, h6 {
- line-height: 1.2;
- }
-
- table {
- max-width: 800px !important;
- font-size: 0.8em;
- width: 100% !important;
- }
-
- table td {
- width: auto !important;
- }
- </style>
- @endif
-
- @include('partials.custom-head')
-</head>
-<body>
-
-<div id="page-show">
- <div class="page-content">
-
- @include('pages.page-display')
-
- <hr>
-
- <div class="text-muted text-small">
- @include('partials.entity-export-meta', ['entity' => $page])
- </div>
+ <hr>
+ <div class="text-muted text-small">
+ @include('partials.entity-export-meta', ['entity' => $page])
</div>
-</div>
-
-</body>
-</html>
+@endsection
\ No newline at end of file
option:markdown-editor:page-id="{{ $model->id ?? 0 }}"
option:markdown-editor:text-direction="{{ config('app.rtl') ? 'rtl' : 'ltr' }}"
option:markdown-editor:image-upload-error-text="{{ trans('errors.image_upload_error') }}"
+ option:markdown-editor:server-upload-limit-text="{{ trans('errors.server_upload_limit') }}"
class="flex-fill flex code-fill">
<div class="markdown-editor-wrap active">
<td><small>{{ $revision->created_at->formatLocalized('%e %B %Y %H:%M:%S') }} <br> ({{ $revision->created_at->diffForHumans() }})</small></td>
<td>{{ $revision->summary }}</td>
<td class="actions">
- <a href="{{ $revision->getUrl('changes') }}" target="_blank">{{ trans('entities.pages_revisions_changes') }}</a>
+ <a href="{{ $revision->getUrl('changes') }}" target="_blank" rel="noopener">{{ trans('entities.pages_revisions_changes') }}</a>
<span class="text-muted"> | </span>
@if ($index === 0)
- <a target="_blank" href="{{ $page->getUrl() }}"><i>{{ trans('entities.pages_revisions_current') }}</i></a>
+ <a target="_blank" rel="noopener" href="{{ $page->getUrl() }}"><i>{{ trans('entities.pages_revisions_current') }}</i></a>
@else
- <a href="{{ $revision->getUrl() }}" target="_blank">{{ trans('entities.pages_revisions_preview') }}</a>
+ <a href="{{ $revision->getUrl() }}" target="_blank" rel="noopener">{{ trans('entities.pages_revisions_preview') }}</a>
<span class="text-muted"> | </span>
<div component="dropdown" class="dropdown-container">
<a refs="dropdown@toggle" href="#" aria-haspopup="true" aria-expanded="false">{{ trans('entities.pages_revisions_restore') }}</a>
@extends('tri-layout')
+@push('social-meta')
+ <meta property="og:description" content="{{ Str::limit($page->text, 100, '...') }}">
+@endpush
+
@section('body')
<div class="mb-m print-hidden">
</div>
</main>
+ @include('partials.entity-sibling-navigation', ['next' => $next, 'previous' => $previous])
+
@if ($commentsEnabled)
- <div class="container small p-none comments-container mb-l print-hidden">
+ @if(($previous || $next))
+ <div class="px-xl">
+ <hr class="darker">
+ </div>
+ @endif
+
+ <div class="px-xl comments-container mb-l print-hidden">
@include('comments.comments', ['page' => $page])
<div class="clearfix"></div>
</div>
<hr class="primary-background"/>
- {{--Export--}}
+ @if(signedInUser())
+ @include('partials.entity-favourite-action', ['entity' => $page])
+ @endif
@include('partials.entity-export-menu', ['entity' => $page])
</div>
option:wysiwyg-editor:page-id="{{ $model->id ?? 0 }}"
option:wysiwyg-editor:text-direction="{{ config('app.rtl') ? 'rtl' : 'ltr' }}"
option:wysiwyg-editor:image-upload-error-text="{{ trans('errors.image_upload_error') }}"
+ option:wysiwyg-editor:server-upload-limit-text="{{ trans('errors.server_upload_limit') }}"
class="flex-fill flex">
<textarea id="html-editor" name="html" rows="5"
+++ /dev/null
-@if(setting('app-custom-head', false))
- <!-- Custom user content -->
- {!! setting('app-custom-head') !!}
- <!-- End custom user content -->
-@endif
\ No newline at end of file
@if(setting('app-custom-head') && \Route::currentRouteName() !== 'settings')
- <!-- Custom user content -->
- {!! setting('app-custom-head') !!}
- <!-- End custom user content -->
+<!-- Custom user content -->
+{!! setting('app-custom-head') !!}
+<!-- End custom user content -->
@endif
\ No newline at end of file
<span>{{ trans('entities.export') }}</span>
</div>
<ul refs="dropdown@menu" class="wide dropdown-menu" role="menu">
- <li><a href="{{ $entity->getUrl('/export/html') }}" target="_blank">{{ trans('entities.export_html') }} <span class="text-muted float right">.html</span></a></li>
- <li><a href="{{ $entity->getUrl('/export/pdf') }}" target="_blank">{{ trans('entities.export_pdf') }} <span class="text-muted float right">.pdf</span></a></li>
- <li><a href="{{ $entity->getUrl('/export/plaintext') }}" target="_blank">{{ trans('entities.export_text') }} <span class="text-muted float right">.txt</span></a></li>
+ <li><a href="{{ $entity->getUrl('/export/html') }}" target="_blank" rel="noopener">{{ trans('entities.export_html') }} <span class="text-muted float right">.html</span></a></li>
+ <li><a href="{{ $entity->getUrl('/export/pdf') }}" target="_blank" rel="noopener">{{ trans('entities.export_pdf') }} <span class="text-muted float right">.pdf</span></a></li>
+ <li><a href="{{ $entity->getUrl('/export/plaintext') }}" target="_blank" rel="noopener">{{ trans('entities.export_text') }} <span class="text-muted float right">.txt</span></a></li>
+ <li><a href="{{ $entity->getUrl('/export/markdown') }}" target="_blank" rel="noopener">{{ trans('entities.export_md') }} <span class="text-muted float right">.md</span></a></li>
</ul>
-</div>
\ No newline at end of file
+</div>
@endif
@icon('star'){!! trans('entities.meta_created' . ($entity->createdBy ? '_name' : ''), [
- 'timeLength' => $entity->created_at->toDayDateTimeString(),
- 'user' => htmlentities($entity->createdBy->name),
+ 'timeLength' => $entity->created_at->formatLocalized('%e %B %Y %H:%M:%S'),
+ 'user' => e($entity->createdBy->name ?? ''),
]) !!}
<br>
@icon('edit'){!! trans('entities.meta_updated' . ($entity->updatedBy ? '_name' : ''), [
- 'timeLength' => $entity->updated_at->toDayDateTimeString(),
- 'user' => htmlentities($entity->updatedBy->name)
+ 'timeLength' => $entity->updated_at->formatLocalized('%e %B %Y %H:%M:%S'),
+ 'user' => e($entity->updatedBy->name ?? '')
]) !!}
</div>
\ No newline at end of file
--- /dev/null
+@php
+ $isFavourite = $entity->isFavourite();
+@endphp
+<form action="{{ url('/favourites/' . ($isFavourite ? 'remove' : 'add')) }}" method="POST">
+ {{ csrf_field() }}
+ <input type="hidden" name="type" value="{{ get_class($entity) }}">
+ <input type="hidden" name="id" value="{{ $entity->id }}">
+ <button type="submit" class="icon-list-item text-primary">
+ <span>@icon($isFavourite ? 'star' : 'star-outline')</span>
+ <span>{{ $isFavourite ? trans('common.unfavourite') : trans('common.favourite') }}</span>
+ </button>
+</form>
\ No newline at end of file
@component('partials.entity-list-item-basic', ['entity' => $entity])
+
<div class="entity-item-snippet">
@if($showPath ?? false)
<p class="text-muted break-text">{{ $entity->getExcerpt() }}</p>
</div>
+
+@if(($showTags ?? false) && $entity->tags->count() > 0)
+ <div class="entity-item-tags mt-xs">
+ @include('components.tag-list', ['entity' => $entity, 'linked' => false ])
+ </div>
+@endif
+
@endcomponent
\ No newline at end of file
@if(count($entities) > 0)
<div class="entity-list {{ $style ?? '' }}">
@foreach($entities as $index => $entity)
- @include('partials.entity-list-item', ['entity' => $entity, 'showPath' => $showPath ?? false])
+ @include('partials.entity-list-item', ['entity' => $entity, 'showPath' => $showPath ?? false, 'showTags' => $showTags ?? false])
@endforeach
</div>
@else
</div>
@endif
- @if ($entity->ownedBy && $entity->ownedBy->id !== $entity->createdBy->id)
+ @if ($entity->ownedBy && $entity->owned_by !== $entity->created_by)
<div>
@icon('user'){!! trans('entities.meta_owned_name', [
'user' => "<a href='{$entity->ownedBy->getProfileUrl()}'>".e($entity->ownedBy->name). "</a>"
--- /dev/null
+<div id="sibling-navigation" class="grid half collapse-xs items-center mb-m px-m no-row-gap fade-in-when-active print-hidden">
+ <div>
+ @if($previous)
+ <a href="{{ $previous->getUrl() }}" class="outline-hover no-link-style block rounded">
+ <div class="px-m pt-xs text-muted">{{ trans('common.previous') }}</div>
+ <div class="inline-block">
+ <div class="icon-list-item no-hover">
+ <span class="text-{{ $previous->getType() }} ">@icon($previous->getType())</span>
+ <span>{{ $previous->getShortName(48) }}</span>
+ </div>
+ </div>
+ </a>
+ @endif
+ </div>
+ <div>
+ @if($next)
+ <a href="{{ $next->getUrl() }}" class="outline-hover no-link-style block rounded text-xs-right">
+ <div class="px-m pt-xs text-muted text-xs-right">{{ trans('common.next') }}</div>
+ <div class="inline block">
+ <div class="icon-list-item no-hover">
+ <span class="text-{{ $next->getType() }} ">@icon($next->getType())</span>
+ <span>{{ $next->getShortName(48) }}</span>
+ </div>
+ </div>
+ </a>
+ @endif
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+@if(setting('app-custom-head'))
+<!-- Custom user content -->
+{!! \BookStack\Util\HtmlContentFilter::removeScripts(setting('app-custom-head')) !!}
+<!-- End custom user content -->
+@endif
\ No newline at end of file
@if ($format === 'pdf')
<style>
+
+ /* PDF size adjustments */
+ body {
+ font-size: 14px;
+ line-height: 1.2;
+ }
+
+ h1, h2, h3, h4, h5, h6 {
+ line-height: 1.2;
+ }
+
+ table {
+ max-width: 800px !important;
+ font-size: 0.8em;
+ width: 100% !important;
+ }
+
+ table td {
+ width: auto !important;
+ }
+
/* Patches for CSS variable colors */
a {
color: {{ setting('app-color') }};
<h6 class="text-muted">{{ trans_choice('entities.search_total_results_found', $totalResults, ['count' => $totalResults]) }}</h6>
<div class="book-contents">
- @include('partials.entity-list', ['entities' => $entities, 'showPath' => true])
+ @include('partials.entity-list', ['entities' => $entities, 'showPath' => true, 'showTags' => true])
</div>
@if($hasNextPage)
<div class="form-group title-input">
<label for="name">{{ trans('common.name') }}</label>
- @include('form.text', ['name' => 'name'])
+ @include('form.text', ['name' => 'name', 'autofocus' => true])
</div>
<div class="form-group description-input">
@extends('tri-layout')
+@push('social-meta')
+ <meta property="og:description" content="{{ Str::limit($shelf->description, 100, '...') }}">
+ @if($shelf->cover)
+ <meta property="og:image" content="{{ $shelf->getBookCover() }}">
+ @endif
+@endpush
+
@section('body')
<div class="mb-s">
</a>
@endif
+ @if(signedInUser())
+ <hr class="primary-background">
+ @include('partials.entity-favourite-action', ['entity' => $shelf])
+ @endif
+
</div>
</div>
@stop
<div class="flex-fill flex">
<div class="content flex">
- <div class="scroll-body">
+ <div id="main-content" class="scroll-body">
@yield('body')
</div>
</div>
@extends('base')
@section('body-class', 'tri-layout')
+@section('content-components', 'tri-layout')
@section('content')
- <div class="tri-layout-mobile-tabs text-primary print-hidden">
+ <div class="tri-layout-mobile-tabs print-hidden">
<div class="grid half no-break no-gap">
- <div class="tri-layout-mobile-tab px-m py-s" tri-layout-mobile-tab="info">
+ <button type="button"
+ refs="tri-layout@tab"
+ data-tab="info"
+ aria-label="{{ trans('common.tab_info_label') }}"
+ class="tri-layout-mobile-tab px-m py-m text-primary">
{{ trans('common.tab_info') }}
- </div>
- <div class="tri-layout-mobile-tab px-m py-s active" tri-layout-mobile-tab="content">
+ </button>
+ <button type="button"
+ refs="tri-layout@tab"
+ data-tab="content"
+ aria-label="{{ trans('common.tab_content_label') }}"
+ aria-selected="true"
+ class="tri-layout-mobile-tab px-m py-m text-primary active">
{{ trans('common.tab_content') }}
- </div>
+ </button>
</div>
</div>
- <div class="tri-layout-container" tri-layout @yield('container-attrs') >
+ <div refs="tri-layout@container" class="tri-layout-container" @yield('container-attrs') >
<div class="tri-layout-left print-hidden pt-m" id="sidebar">
<aside class="tri-layout-left-contents">
</div>
<div class="@yield('body-wrap-classes') tri-layout-middle">
- <div class="tri-layout-middle-contents">
+ <div id="main-content" class="tri-layout-middle-contents">
@yield('body')
</div>
</div>
<div role="presentation">@icon('auth/'. $driver, ['style' => 'width: 56px;height: 56px;'])</div>
<div>
@if($user->hasSocialAccount($driver))
- <a href="{{ url("/login/service/{$driver}/detach") }}" aria-label="{{ trans('settings.users_social_disconnect') }} - {{ $driver }}"
- class="button small outline">{{ trans('settings.users_social_disconnect') }}</a>
+ <form action="{{ url("/login/service/{$driver}/detach") }}" method="POST">
+ {{ csrf_field() }}
+ <button aria-label="{{ trans('settings.users_social_disconnect') }} - {{ $driver }}"
+ class="button small outline">{{ trans('settings.users_social_disconnect') }}</button>
+ </form>
@else
<a href="{{ url("/login/service/{$driver}") }}" aria-label="{{ trans('settings.users_social_connect') }} - {{ $driver }}"
class="button small outline">{{ trans('settings.users_social_connect') }}</a>
<main class="card content-wrap">
- <div class="grid right-focus v-center">
+ <div class="flex-container-row wrap justify-space-between items-center">
<h1 class="list-heading">{{ trans('settings.users') }}</h1>
- <div class="text-right">
- <div class="block inline mr-s">
+ <div>
+ <div class="block inline mr-xs">
<form method="get" action="{{ url("/settings/users") }}">
@foreach(collect($listDetails)->except('search') as $name => $val)
<input type="hidden" name="{{ $name }}" value="{{ $val }}">
Route::get('books/{id}/export/html', 'BookExportApiController@exportHtml');
Route::get('books/{id}/export/pdf', 'BookExportApiController@exportPdf');
Route::get('books/{id}/export/plaintext', 'BookExportApiController@exportPlainText');
+Route::get('books/{id}/export/markdown', 'BookExportApiController@exportMarkdown');
Route::get('chapters', 'ChapterApiController@list');
Route::post('chapters', 'ChapterApiController@create');
Route::get('chapters/{id}/export/html', 'ChapterExportApiController@exportHtml');
Route::get('chapters/{id}/export/pdf', 'ChapterExportApiController@exportPdf');
Route::get('chapters/{id}/export/plaintext', 'ChapterExportApiController@exportPlainText');
+Route::get('chapters/{id}/export/markdown', 'ChapterExportApiController@exportMarkdown');
Route::get('pages', 'PageApiController@list');
Route::post('pages', 'PageApiController@create');
Route::get('pages/{id}/export/html', 'PageExportApiController@exportHtml');
Route::get('pages/{id}/export/pdf', 'PageExportApiController@exportPdf');
Route::get('pages/{id}/export/plaintext', 'PageExportApiController@exportPlainText');
+Route::get('pages/{id}/export/markdown', 'PageExportApiController@exportMarkDown');
Route::get('shelves', 'BookshelfApiController@list');
Route::post('shelves', 'BookshelfApiController@create');
// Shelves
Route::get('/create-shelf', 'BookshelfController@create');
- Route::group(['prefix' => 'shelves'], function() {
+ Route::group(['prefix' => 'shelves'], function () {
Route::get('/', 'BookshelfController@index');
Route::post('/', 'BookshelfController@store');
Route::get('/{slug}/edit', 'BookshelfController@edit');
Route::put('/{bookSlug}/sort', 'BookSortController@update');
Route::get('/{bookSlug}/export/html', 'BookExportController@html');
Route::get('/{bookSlug}/export/pdf', 'BookExportController@pdf');
+ Route::get('/{bookSlug}/export/markdown', 'BookExportController@markdown');
+ Route::get('/{bookSlug}/export/zip', 'BookExportController@zip');
Route::get('/{bookSlug}/export/plaintext', 'BookExportController@plainText');
// Pages
Route::get('/{bookSlug}/page/{pageSlug}', 'PageController@show');
Route::get('/{bookSlug}/page/{pageSlug}/export/pdf', 'PageExportController@pdf');
Route::get('/{bookSlug}/page/{pageSlug}/export/html', 'PageExportController@html');
+ Route::get('/{bookSlug}/page/{pageSlug}/export/markdown', 'PageExportController@markdown');
Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', 'PageExportController@plainText');
Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit');
Route::get('/{bookSlug}/page/{pageSlug}/move', 'PageController@showMove');
Route::get('/{bookSlug}/chapter/{chapterSlug}/permissions', 'ChapterController@showPermissions');
Route::get('/{bookSlug}/chapter/{chapterSlug}/export/pdf', 'ChapterExportController@pdf');
Route::get('/{bookSlug}/chapter/{chapterSlug}/export/html', 'ChapterExportController@html');
+ Route::get('/{bookSlug}/chapter/{chapterSlug}/export/markdown', 'ChapterExportController@markdown');
Route::get('/{bookSlug}/chapter/{chapterSlug}/export/plaintext', 'ChapterExportController@plainText');
Route::put('/{bookSlug}/chapter/{chapterSlug}/permissions', 'ChapterController@permissions');
Route::get('/{bookSlug}/chapter/{chapterSlug}/delete', 'ChapterController@showDelete');
// User Search
Route::get('/search/users/select', 'UserSearchController@forSelect');
+ // Template System
Route::get('/templates', 'PageTemplateController@list');
Route::get('/templates/{templateId}', 'PageTemplateController@get');
+ // Favourites
+ Route::get('/favourites', 'FavouriteController@index');
+ Route::post('/favourites/add', 'FavouriteController@add');
+ Route::post('/favourites/remove', 'FavouriteController@remove');
+
// Other Pages
Route::get('/', 'HomeController@index');
Route::get('/home', 'HomeController@index');
Route::get('/login/service/{socialDriver}', 'Auth\SocialController@login');
Route::get('/login/service/{socialDriver}/callback', 'Auth\SocialController@callback');
Route::group(['middleware' => 'auth'], function () {
- Route::get('/login/service/{socialDriver}/detach', 'Auth\SocialController@detach');
+ Route::post('/login/service/{socialDriver}/detach', 'Auth\SocialController@detach');
});
Route::get('/register/service/{socialDriver}', 'Auth\SocialController@register');
Route::get('/password/reset/{token}', 'Auth\ResetPasswordController@showResetForm');
Route::post('/password/reset', 'Auth\ResetPasswordController@reset');
-Route::fallback('HomeController@getNotFound');
\ No newline at end of file
+Route::fallback('HomeController@getNotFound')->name('fallback');
\ No newline at end of file
$resp->assertStatus(200);
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.pdf"');
}
+
+ public function test_export_markdown_endpoint()
+ {
+ $this->actingAsApiEditor();
+ $book = Book::visible()->has('pages')->has('chapters')->first();
+
+ $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/markdown");
+ $resp->assertStatus(200);
+ $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.md"');
+ $resp->assertSee('# ' . $book->name);
+ $resp->assertSee('# ' . $book->pages()->first()->name);
+ $resp->assertSee('# ' . $book->chapters()->first()->name);
+ }
}
\ No newline at end of file
$resp->assertStatus(200);
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.pdf"');
}
+
+ public function test_export_markdown_endpoint()
+ {
+ $this->actingAsApiEditor();
+ $chapter = Chapter::visible()->has('pages')->first();
+
+ $resp = $this->get($this->baseEndpoint . "/{$chapter->id}/export/markdown");
+ $resp->assertStatus(200);
+ $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.md"');
+ $resp->assertSee('# ' . $chapter->name);
+ $resp->assertSee('# ' . $chapter->pages()->first()->name);
+ }
}
\ No newline at end of file
$resp->assertStatus(200);
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.pdf"');
}
+
+ public function test_export_markdown_endpoint()
+ {
+ $this->actingAsApiEditor();
+ $page = Page::visible()->first();
+
+ $resp = $this->get($this->baseEndpoint . "/{$page->id}/export/markdown");
+ $resp->assertStatus(200);
+ $resp->assertSee('# ' . $page->name);
+ $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.md"');
+ }
}
\ No newline at end of file
use BookStack\Auth\Role;
use BookStack\Auth\Access\Ldap;
use BookStack\Auth\User;
-use BookStack\Exceptions\LdapException;
use Mockery\MockInterface;
-use Tests\BrowserKitTest;
+use Tests\TestCase;
+use Tests\TestResponse;
-class LdapTest extends BrowserKitTest
+class LdapTest extends TestCase
{
-
/**
* @var MockInterface
*/
'services.ldap.user_filter' => '(&(uid=${user}))',
'services.ldap.follow_referrals' => false,
'services.ldap.tls_insecure' => false,
+ 'services.ldap.thumbnail_attribute' => null,
]);
$this->mockLdap = \Mockery::mock(Ldap::class);
$this->app[Ldap::class] = $this->mockLdap;
protected function mockEscapes($times = 1)
{
- $this->mockLdap->shouldReceive('escape')->times($times)->andReturnUsing(function($val) {
+ $this->mockLdap->shouldReceive('escape')->times($times)->andReturnUsing(function ($val) {
return ldap_escape($val);
});
}
protected function mockExplodes($times = 1)
{
- $this->mockLdap->shouldReceive('explodeDn')->times($times)->andReturnUsing(function($dn, $withAttrib) {
+ $this->mockLdap->shouldReceive('explodeDn')->times($times)->andReturnUsing(function ($dn, $withAttrib) {
return ldap_explode_dn($dn, $withAttrib);
});
}
- protected function mockUserLogin()
+ protected function mockUserLogin(?string $email = null): TestResponse
{
- return $this->visit('/login')
- ->see('Username')
- ->type($this->mockUser->name, '#username')
- ->type($this->mockUser->password, '#password')
- ->press('Log In');
+ return $this->post('/login', [
+ 'username' => $this->mockUser->name,
+ 'password' => $this->mockUser->password,
+ ] + ($email ? ['email' => $email] : []));
}
/**
'dn' => ['dc=test' . config('services.ldap.base_dn')]
]]);
- $this->mockUserLogin()
- ->seePageIs('/login')->see('Please enter an email to use for this account.');
-
- $this->type($this->mockUser->email, '#email')
- ->press('Log In')
- ->seePageIs('/')
- ->see($this->mockUser->name)
- ->seeInDatabase('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => $this->mockUser->name]);
+ $resp = $this->mockUserLogin();
+ $resp->assertRedirect('/login');
+ $resp = $this->followRedirects($resp);
+ $resp->assertSee('Please enter an email to use for this account.');
+ $resp->assertSee($this->mockUser->name);
+
+ $resp = $this->followingRedirects()->mockUserLogin($this->mockUser->email);
+ $resp->assertElementExists('#home-default');
+ $resp->assertSee($this->mockUser->name);
+ $this->assertDatabaseHas('users', [
+ 'email' => $this->mockUser->email,
+ 'email_confirmed' => false,
+ 'external_auth_id' => $this->mockUser->name
+ ]);
}
public function test_email_domain_restriction_active_on_new_ldap_login()
'dn' => ['dc=test' . config('services.ldap.base_dn')]
]]);
- $this->mockUserLogin()
- ->seePageIs('/login')
- ->see('Please enter an email to use for this account.');
+ $resp = $this->mockUserLogin();
+ $resp->assertRedirect('/login');
+ $this->followRedirects($resp)->assertSee('Please enter an email to use for this account.');
+
+ $resp = $this->mockUserLogin($email);
+ $resp->assertRedirect('/login');
+ $this->followRedirects($resp)->assertSee('That email domain does not have access to this application');
- $this->type($email, '#email')
- ->press('Log In')
- ->seePageIs('/login')
- ->see('That email domain does not have access to this application')
- ->dontSeeInDatabase('users', ['email' => $email]);
+ $this->assertDatabaseMissing('users', ['email' => $email]);
}
public function test_login_works_when_no_uid_provided_by_ldap_server()
'mail' => [$this->mockUser->email]
]]);
- $this->mockUserLogin()
- ->seePageIs('/')
- ->see($this->mockUser->name)
- ->seeInDatabase('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => $ldapDn]);
+ $resp = $this->mockUserLogin();
+ $resp->assertRedirect('/');
+ $this->followRedirects($resp)->assertSee($this->mockUser->name);
+ $this->assertDatabaseHas('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => $ldapDn]);
}
public function test_a_custom_uid_attribute_can_be_specified_and_is_used_properly()
]]);
- $this->mockUserLogin()
- ->seePageIs('/')
- ->see($this->mockUser->name)
- ->seeInDatabase('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => 'cooluser456']);
+ $resp = $this->mockUserLogin();
+ $resp->assertRedirect('/');
+ $this->followRedirects($resp)->assertSee($this->mockUser->name);
+ $this->assertDatabaseHas('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => 'cooluser456']);
}
public function test_initial_incorrect_credentials()
]]);
$this->mockLdap->shouldReceive('bind')->times(2)->andReturn(true, false);
- $this->mockUserLogin()
- ->seePageIs('/login')->see('These credentials do not match our records.')
- ->dontSeeInDatabase('users', ['external_auth_id' => $this->mockUser->name]);
+ $resp = $this->mockUserLogin();
+ $resp->assertRedirect('/login');
+ $this->followRedirects($resp)->assertSee('These credentials do not match our records.');
+ $this->assertDatabaseMissing('users', ['external_auth_id' => $this->mockUser->name]);
}
public function test_login_not_found_username()
->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array'))
->andReturn(['count' => 0]);
- $this->mockUserLogin()
- ->seePageIs('/login')->see('These credentials do not match our records.')
- ->dontSeeInDatabase('users', ['external_auth_id' => $this->mockUser->name]);
+ $resp = $this->mockUserLogin();
+ $resp->assertRedirect('/login');
+ $this->followRedirects($resp)->assertSee('These credentials do not match our records.');
+ $this->assertDatabaseMissing('users', ['external_auth_id' => $this->mockUser->name]);
}
-
public function test_create_user_form()
{
- $this->asAdmin()->visit('/settings/users/create')
- ->dontSee('Password')
- ->type($this->mockUser->name, '#name')
- ->type($this->mockUser->email, '#email')
- ->press('Save')
- ->see('The external auth id field is required.')
- ->type($this->mockUser->name, '#external_auth_id')
- ->press('Save')
- ->seePageIs('/settings/users')
- ->seeInDatabase('users', ['email' => $this->mockUser->email, 'external_auth_id' => $this->mockUser->name, 'email_confirmed' => true]);
+ $userForm = $this->asAdmin()->get('/settings/users/create');
+ $userForm->assertDontSee('Password');
+
+ $save = $this->post('/settings/users/create', [
+ 'name' => $this->mockUser->name,
+ 'email' => $this->mockUser->email,
+ ]);
+ $save->assertSessionHasErrors(['external_auth_id' => 'The external auth id field is required.']);
+
+ $save = $this->post('/settings/users/create', [
+ 'name' => $this->mockUser->name,
+ 'email' => $this->mockUser->email,
+ 'external_auth_id' => $this->mockUser->name,
+ ]);
+ $save->assertRedirect('/settings/users');
+ $this->assertDatabaseHas('users', ['email' => $this->mockUser->email, 'external_auth_id' => $this->mockUser->name, 'email_confirmed' => true]);
}
public function test_user_edit_form()
{
$editUser = $this->getNormalUser();
- $this->asAdmin()->visit('/settings/users/' . $editUser->id)
- ->see('Edit User')
- ->dontSee('Password')
- ->type('test_auth_id', '#external_auth_id')
- ->press('Save')
- ->seePageIs('/settings/users')
- ->seeInDatabase('users', ['email' => $editUser->email, 'external_auth_id' => 'test_auth_id']);
+ $editPage = $this->asAdmin()->get("/settings/users/{$editUser->id}");
+ $editPage->assertSee('Edit User');
+ $editPage->assertDontSee('Password');
+
+ $update = $this->put("/settings/users/{$editUser->id}", [
+ 'name' => $editUser->name,
+ 'email' => $editUser->email,
+ 'external_auth_id' => 'test_auth_id',
+ ]);
+ $update->assertRedirect('/settings/users');
+ $this->assertDatabaseHas('users', ['email' => $editUser->email, 'external_auth_id' => 'test_auth_id']);
}
public function test_registration_disabled()
{
- $this->visit('/register')
- ->seePageIs('/login');
+ $this->followingRedirects()->get('/register')->assertElementContains('#content', 'Log In');
}
public function test_non_admins_cannot_change_auth_id()
{
$testUser = $this->getNormalUser();
- $this->actingAs($testUser)->visit('/settings/users/' . $testUser->id)
- ->dontSee('External Authentication');
+ $this->actingAs($testUser)
+ ->get('/settings/users/' . $testUser->id)
+ ->assertDontSee('External Authentication');
}
public function test_login_maps_roles_and_retains_existing_roles()
]
]]);
- $this->mockUserLogin()->seePageIs('/');
+ $this->mockUserLogin()->assertRedirect('/');
$user = User::where('email', $this->mockUser->email)->first();
- $this->seeInDatabase('role_user', [
+ $this->assertDatabaseHas('role_user', [
'user_id' => $user->id,
'role_id' => $roleToReceive->id
]);
- $this->seeInDatabase('role_user', [
+ $this->assertDatabaseHas('role_user', [
'user_id' => $user->id,
'role_id' => $roleToReceive2->id
]);
- $this->seeInDatabase('role_user', [
+ $this->assertDatabaseHas('role_user', [
'user_id' => $user->id,
'role_id' => $existingRole->id
]);
]
]]);
- $this->mockUserLogin()->seePageIs('/');
+ $this->mockUserLogin()->assertRedirect('/');
- $user = User::where('email', $this->mockUser->email)->first();
- $this->seeInDatabase('role_user', [
+ $user = User::query()->where('email', $this->mockUser->email)->first();
+ $this->assertDatabaseHas('role_user', [
'user_id' => $user->id,
'role_id' => $roleToReceive->id
]);
- $this->dontSeeInDatabase('role_user', [
+ $this->assertDatabaseMissing('role_user', [
'user_id' => $user->id,
'role_id' => $existingRole->id
]);
public function test_external_auth_id_visible_in_roles_page_when_ldap_active()
{
$role = factory(Role::class)->create(['display_name' => 'ldaptester', 'external_auth_id' => 'ex-auth-a, test-second-param']);
- $this->asAdmin()->visit('/settings/roles/' . $role->id)
- ->see('ex-auth-a');
+ $this->asAdmin()->get('/settings/roles/' . $role->id)
+ ->assertSee('ex-auth-a');
}
public function test_login_maps_roles_using_external_auth_ids_if_set()
]
]]);
- $this->mockUserLogin()->seePageIs('/');
+ $this->mockUserLogin()->assertRedirect('/');
- $user = User::where('email', $this->mockUser->email)->first();
- $this->seeInDatabase('role_user', [
+ $user = User::query()->where('email', $this->mockUser->email)->first();
+ $this->assertDatabaseHas('role_user', [
'user_id' => $user->id,
'role_id' => $roleToReceive->id
]);
- $this->dontSeeInDatabase('role_user', [
+ $this->assertDatabaseMissing('role_user', [
'user_id' => $user->id,
'role_id' => $roleToNotReceive->id
]);
]
]]);
- $this->mockUserLogin()->seePageIs('/');
+ $this->mockUserLogin()->assertRedirect('/');
- $user = User::where('email', $this->mockUser->email)->first();
- $this->seeInDatabase('role_user', [
+ $user = User::query()->where('email', $this->mockUser->email)->first();
+ $this->assertDatabaseHas('role_user', [
'user_id' => $user->id,
'role_id' => $roleToReceive->id
]);
- $this->seeInDatabase('role_user', [
+ $this->assertDatabaseHas('role_user', [
'user_id' => $user->id,
'role_id' => $roleToReceive2->id
]);
'displayname' => 'displayNameAttribute'
]]);
- $this->mockUserLogin()
- ->seePageIs('/login')->see('Please enter an email to use for this account.');
+ $this->mockUserLogin()->assertRedirect('/login');
+ $this->get('/login')->assertSee('Please enter an email to use for this account.');
- $this->type($this->mockUser->email, '#email')
- ->press('Log In')
- ->seePageIs('/')
- ->see('displayNameAttribute')
- ->seeInDatabase('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => $this->mockUser->name, 'name' => 'displayNameAttribute']);
+ $resp = $this->mockUserLogin($this->mockUser->email);
+ $resp->assertRedirect('/');
+ $this->get('/')->assertSee('displayNameAttribute');
+ $this->assertDatabaseHas('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => $this->mockUser->name, 'name' => 'displayNameAttribute']);
}
public function test_login_uses_default_display_name_attribute_if_specified_not_present()
'dn' => ['dc=test' . config('services.ldap.base_dn')]
]]);
- $this->mockUserLogin()
- ->seePageIs('/login')->see('Please enter an email to use for this account.');
+ $this->mockUserLogin()->assertRedirect('/login');
+ $this->get('/login')->assertSee('Please enter an email to use for this account.');
- $this->type($this->mockUser->email, '#email')
- ->press('Log In')
- ->seePageIs('/')
- ->see($this->mockUser->name)
- ->seeInDatabase('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => $this->mockUser->name, 'name' => $this->mockUser->name]);
+ $resp = $this->mockUserLogin($this->mockUser->email);
+ $resp->assertRedirect('/');
+ $this->get('/')->assertSee($this->mockUser->name);
+ $this->assertDatabaseHas('users', [
+ 'email' => $this->mockUser->email,
+ 'email_confirmed' => false,
+ 'external_auth_id' => $this->mockUser->name,
+ 'name' => $this->mockUser->name
+ ]);
}
protected function checkLdapReceivesCorrectDetails($serverString, $expectedHost, $expectedPort)
'dn' => ['dc=test' . config('services.ldap.base_dn')]
]]);
- $this->post('/login', [
+ $resp = $this->post('/login', [
'username' => $this->mockUser->name,
'password' => $this->mockUser->password,
]);
- $this->seeJsonStructure([
+ $resp->assertJsonStructure([
'details_from_ldap' => [],
'details_bookstack_parsed' => [],
]);
config()->set(['services.ldap.start_tls' => true]);
$this->mockLdap->shouldReceive('startTls')->once()->andReturn(false);
$this->commonLdapMocks(1, 1, 0, 0, 0);
- $this->post('/login', ['username' => 'timmyjenkins', 'password' => 'cattreedog']);
- $this->assertResponseStatus(500);
+ $resp = $this->post('/login', ['username' => 'timmyjenkins', 'password' => 'cattreedog']);
+ $resp->assertStatus(500);
}
public function test_ldap_attributes_can_be_binary_decoded_if_marked()
]]);
// First user login
- $this->mockUserLogin()->seePageIs('/');
+ $this->mockUserLogin()->assertRedirect('/');
// Second user login
auth()->logout();
- $this->post('/login', ['username' => 'bscott', 'password' => 'pass'])->followRedirects();
-
- $this->see('A user with the email
[email protected] already exists but with different credentials');
+ $resp = $this->followingRedirects()->post('/login', ['username' => 'bscott', 'password' => 'pass']);
+ $resp->assertSee('A user with the email
[email protected] already exists but with different credentials');
}
public function test_login_with_email_confirmation_required_maps_groups_but_shows_confirmation_screen()
]
]]);
- $this->mockUserLogin()->seePageIs('/register/confirm');
- $this->seeInDatabase('users', [
+ $this->followingRedirects()->mockUserLogin()->assertSee('Thanks for registering!');
+ $this->assertDatabaseHas('users', [
'email' => $user->email,
'email_confirmed' => false,
]);
- $user = User::query()->where('email', '=', $user->email)->first();
- $this->seeInDatabase('role_user', [
+ $user = User::query()->where('email', '=', $user->email)->first();
+ $this->assertDatabaseHas('role_user', [
'user_id' => $user->id,
'role_id' => $roleToReceive->id
]);
$homePage = $this->get('/');
- $homePage->assertRedirectedTo('/register/confirm/awaiting');
+ $homePage->assertRedirect('/register/confirm/awaiting');
}
public function test_failed_logins_are_logged_when_message_configured()
$this->runFailedAuthLogin();
$this->assertTrue($log->hasWarningThatContains('Failed login for timmyjenkins'));
}
+
+ public function test_thumbnail_attribute_used_as_user_avatar_if_configured()
+ {
+ config()->set(['services.ldap.thumbnail_attribute' => 'jpegPhoto']);
+
+ $this->commonLdapMocks(1, 1, 1, 2, 1);
+ $ldapDn = 'cn=test-user,dc=test' . config('services.ldap.base_dn');
+ $this->mockLdap->shouldReceive('searchAndGetEntries')->times(1)
+ ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array'))
+ ->andReturn(['count' => 1, 0 => [
+ 'cn' => [$this->mockUser->name],
+ 'dn' => $ldapDn,
+ 'jpegphoto' => [base64_decode('/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8Q
+EBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=')],
+ 'mail' => [$this->mockUser->email]
+ ]]);
+
+ $this->mockUserLogin()
+ ->assertRedirect('/');
+
+ $user = User::query()->where('email', '=', $this->mockUser->email)->first();
+ $this->assertNotNull($user->avatar);
+ $this->assertEquals('8c90748342f19b195b9c6b4eff742ded', md5_file(public_path($user->avatar->path)));
+ }
}
'saml2.autoload_from_metadata' => false,
'saml2.onelogin.idp.x509cert' => $this->testCert,
'saml2.onelogin.debug' => false,
+ 'saml2.onelogin.security.requestedAuthnContext' => true,
]);
}
});
}
+ public function test_login_request_contains_expected_default_authncontext()
+ {
+ $authReq = $this->getAuthnRequest();
+ $this->assertStringContainsString('samlp:RequestedAuthnContext Comparison="exact"', $authReq);
+ $this->assertStringContainsString('<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>', $authReq);
+ }
+
+ public function test_false_idp_authncontext_option_does_not_pass_authncontext_in_saml_request()
+ {
+ config()->set(['saml2.onelogin.security.requestedAuthnContext' => false]);
+ $authReq = $this->getAuthnRequest();
+ $this->assertStringNotContainsString('samlp:RequestedAuthnContext', $authReq);
+ $this->assertStringNotContainsString('<saml:AuthnContextClassRef>', $authReq);
+ }
+
+ public function test_array_idp_authncontext_option_passes_value_as_authncontextclassref_in_request()
+ {
+ config()->set(['saml2.onelogin.security.requestedAuthnContext' => ['urn:federation:authentication:windows', 'urn:federation:authentication:linux']]);
+ $authReq = $this->getAuthnRequest();
+ $this->assertStringContainsString('samlp:RequestedAuthnContext', $authReq);
+ $this->assertStringContainsString('<saml:AuthnContextClassRef>urn:federation:authentication:windows</saml:AuthnContextClassRef>', $authReq);
+ $this->assertStringContainsString('<saml:AuthnContextClassRef>urn:federation:authentication:linux</saml:AuthnContextClassRef>', $authReq);
+ }
+
+ protected function getAuthnRequest(): string
+ {
+ $req = $this->post('/saml2/login');
+ $location = $req->headers->get('Location');
+ $query = explode('?', $location)[1];
+ $params = [];
+ parse_str($query, $params);
+ return gzinflate(base64_decode($params['SAMLRequest']));
+ }
+
protected function withGet(array $options, callable $callback)
{
return $this->withGlobal($_GET, $options, $callback);
<?php namespace Tests\Auth;
+use BookStack\Auth\SocialAccount;
use BookStack\Auth\User;
use DB;
use Laravel\Socialite\Contracts\Factory;
$resp->assertDontSee("login-form");
}
+ public function test_social_account_detach()
+ {
+ $editor = $this->getEditor();
+ config([
+ 'GITHUB_APP_ID' => 'abc123', 'GITHUB_APP_SECRET' => '123abc',
+ 'APP_URL' => 'http://localhost'
+ ]);
+
+ $socialAccount = SocialAccount::query()->forceCreate([
+ 'user_id' => $editor->id,
+ 'driver' => 'github',
+ 'driver_id' => 'logintest123',
+ ]);
+
+ $resp = $this->actingAs($editor)->get($editor->getEditUrl());
+ $resp->assertElementContains('form[action$="/login/service/github/detach"]', 'Disconnect Account');
+
+ $resp = $this->post('/login/service/github/detach');
+ $resp->assertRedirect($editor->getEditUrl());
+ $resp = $this->followRedirects($resp);
+ $resp->assertSee('Github account was successfully disconnected from your profile.');
+
+ $this->assertDatabaseMissing('social_accounts', ['id' => $socialAccount->id]);
+ }
+
public function test_social_autoregister()
{
config([
}
- /**
- * Get a user that's not a system user such as the guest user.
- */
- public function getNormalUser()
- {
- return User::where('system_name', '=', null)->get()->last();
- }
-
/**
* Quickly sets an array of settings.
* @param $settingsArray
$redirectReq = $this->get($deleteReq->baseResponse->headers->get('location'));
$redirectReq->assertNotificationContains('Book Successfully Deleted');
}
+
+ public function test_next_previous_navigation_controls_show_within_book_content()
+ {
+ $book = Book::query()->first();
+ $chapter = $book->chapters->first();
+
+ $resp = $this->asEditor()->get($chapter->getUrl());
+ $resp->assertElementContains('#sibling-navigation', 'Next');
+ $resp->assertElementContains('#sibling-navigation', substr($chapter->pages[0]->name, 0, 20));
+
+ $resp = $this->get($chapter->pages[0]->getUrl());
+ $resp->assertElementContains('#sibling-navigation', substr($chapter->pages[1]->name, 0, 20));
+ $resp->assertElementContains('#sibling-navigation', 'Previous');
+ $resp->assertElementContains('#sibling-navigation', substr($chapter->name, 0, 20));
+ }
}
\ No newline at end of file
<?php namespace Tests\Entity;
use BookStack\Entities\Models\Page;
-use Tests\BrowserKitTest;
+use Tests\TestCase;
-class CommentSettingTest extends BrowserKitTest
+class CommentSettingTest extends TestCase
{
protected $page;
public function setUp(): void
{
parent::setUp();
- $this->page = Page::first();
+ $this->page = Page::query()->first();
}
public function test_comment_disable()
{
- $this->asAdmin();
-
$this->setSettings(['app-disable-comments' => 'true']);
+ $this->asAdmin();
- $this->asAdmin()->visit($this->page->getUrl())
- ->pageNotHasElement('.comments-list');
+ $this->asAdmin()->get($this->page->getUrl())
+ ->assertElementNotExists('.comments-list');
}
public function test_comment_enable()
{
- $this->asAdmin();
-
$this->setSettings(['app-disable-comments' => 'false']);
+ $this->asAdmin();
- $this->asAdmin()->visit($this->page->getUrl())
- ->pageHasElement('.comments-list');
+ $this->asAdmin()->get($this->page->getUrl())
+ ->assertElementExists('.comments-list');
}
}
\ No newline at end of file
<?php namespace Tests\Entity;
+use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Page;
use Illuminate\Support\Facades\Storage;
public function test_page_text_export()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asEditor();
$resp = $this->get($page->getUrl('/export/plaintext'));
public function test_page_pdf_export()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asEditor();
$resp = $this->get($page->getUrl('/export/pdf'));
public function test_page_html_export()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asEditor();
$resp = $this->get($page->getUrl('/export/html'));
public function test_book_text_export()
{
- $page = Page::first();
+ $page = Page::query()->first();
$book = $page->book;
$this->asEditor();
public function test_book_pdf_export()
{
- $page = Page::first();
+ $page = Page::query()->first();
$book = $page->book;
$this->asEditor();
public function test_book_html_export()
{
- $page = Page::first();
+ $page = Page::query()->first();
$book = $page->book;
$this->asEditor();
public function test_chapter_text_export()
{
- $chapter = Chapter::first();
+ $chapter = Chapter::query()->first();
$page = $chapter->pages[0];
$this->asEditor();
public function test_chapter_pdf_export()
{
- $chapter = Chapter::first();
+ $chapter = Chapter::query()->first();
$this->asEditor();
$resp = $this->get($chapter->getUrl('/export/pdf'));
public function test_chapter_html_export()
{
- $chapter = Chapter::first();
+ $chapter = Chapter::query()->first();
$page = $chapter->pages[0];
$this->asEditor();
public function test_page_html_export_contains_custom_head_if_set()
{
- $page = Page::first();
+ $page = Page::query()->first();
$customHeadContent = "<style>p{color: red;}</style>";
$this->setSettings(['app-custom-head' => $customHeadContent]);
$resp->assertSee($customHeadContent);
}
+ public function test_page_html_export_does_not_break_with_only_comments_in_custom_head()
+ {
+ $page = Page::query()->first();
+
+ $customHeadContent = "<!-- A comment -->";
+ $this->setSettings(['app-custom-head' => $customHeadContent]);
+
+ $resp = $this->asEditor()->get($page->getUrl('/export/html'));
+ $resp->assertStatus(200);
+ $resp->assertSee($customHeadContent);
+ }
+
public function test_page_html_export_use_absolute_dates()
{
- $page = Page::first();
+ $page = Page::query()->first();
$resp = $this->asEditor()->get($page->getUrl('/export/html'));
- $resp->assertSee($page->created_at->toDayDateTimeString());
+ $resp->assertSee($page->created_at->formatLocalized('%e %B %Y %H:%M:%S'));
$resp->assertDontSee($page->created_at->diffForHumans());
- $resp->assertSee($page->updated_at->toDayDateTimeString());
+ $resp->assertSee($page->updated_at->formatLocalized('%e %B %Y %H:%M:%S'));
$resp->assertDontSee($page->updated_at->diffForHumans());
}
public function test_page_export_does_not_include_user_or_revision_links()
{
- $page = Page::first();
+ $page = Page::query()->first();
$resp = $this->asEditor()->get($page->getUrl('/export/html'));
$resp->assertDontSee($page->getUrl('/revisions'));
public function test_page_export_sets_right_data_type_for_svg_embeds()
{
- $page = Page::first();
+ $page = Page::query()->first();
Storage::disk('local')->makeDirectory('uploads/images/gallery');
Storage::disk('local')->put('uploads/images/gallery/svg_test.svg', '<svg></svg>');
$page->html = '<img src="http://localhost/uploads/images/gallery/svg_test.svg">';
public function test_page_image_containment_works_on_multiple_images_within_a_single_line()
{
- $page = Page::first();
+ $page = Page::query()->first();
Storage::disk('local')->makeDirectory('uploads/images/gallery');
Storage::disk('local')->put('uploads/images/gallery/svg_test.svg', '<svg></svg>');
Storage::disk('local')->put('uploads/images/gallery/svg_test2.svg', '<svg></svg>');
public function test_page_export_contained_html_image_fetches_only_run_when_url_points_to_image_upload_folder()
{
- $page = Page::first();
+ $page = Page::query()->first();
$page->html = '<img src="http://localhost/uploads/images/gallery/svg_test.svg"/>'
.'<img src="http://localhost/uploads/svg_test.svg"/>'
.'<img src="/uploads/svg_test.svg"/>';
$resp->assertSee('src="/uploads/svg_test.svg"');
}
+ public function test_exports_removes_scripts_from_custom_head()
+ {
+ $entities = [
+ Page::query()->first(), Chapter::query()->first(), Book::query()->first(),
+ ];
+ setting()->put('app-custom-head', '<script>window.donkey = "cat";</script><style>.my-test-class { color: red; }</style>');
+
+ foreach ($entities as $entity) {
+ $resp = $this->asEditor()->get($entity->getUrl('/export/html'));
+ $resp->assertDontSee('window.donkey');
+ $resp->assertDontSee('script');
+ $resp->assertSee('.my-test-class { color: red; }');
+ }
+ }
+
+ public function test_page_export_with_deleted_creator_and_updater()
+ {
+ $user = $this->getViewer(['name' => 'ExportWizardTheFifth']);
+ $page = Page::query()->first();
+ $page->created_by = $user->id;
+ $page->updated_by = $user->id;
+ $page->save();
+
+ $resp = $this->asEditor()->get($page->getUrl('/export/html'));
+ $resp->assertSee('ExportWizardTheFifth');
+
+ $user->delete();
+ $resp = $this->get($page->getUrl('/export/html'));
+ $resp->assertStatus(200);
+ $resp->assertDontSee('ExportWizardTheFifth');
+ }
+
+ public function test_page_markdown_export()
+ {
+ $page = Page::query()->first();
+
+ $resp = $this->asEditor()->get($page->getUrl('/export/markdown'));
+ $resp->assertStatus(200);
+ $resp->assertSee($page->name);
+ $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.md"');
+ }
+
+ public function test_page_markdown_export_uses_existing_markdown_if_apparent()
+ {
+ $page = Page::query()->first()->forceFill([
+ 'markdown' => '# A header',
+ 'html' => '<h1>Dogcat</h1>',
+ ]);
+ $page->save();
+
+ $resp = $this->asEditor()->get($page->getUrl('/export/markdown'));
+ $resp->assertSee('A header');
+ $resp->assertDontSee('Dogcat');
+ }
+
+ public function test_page_markdown_export_converts_html_where_no_markdown()
+ {
+ $page = Page::query()->first()->forceFill([
+ 'markdown' => '',
+ 'html' => "<h1>Dogcat</h1><p>Some <strong>bold</strong> text</p>",
+ ]);
+ $page->save();
+
+ $resp = $this->asEditor()->get($page->getUrl('/export/markdown'));
+ $resp->assertSee("# Dogcat\n\nSome **bold** text");
+ }
+
+ public function test_page_markdown_export_does_not_convert_callouts()
+ {
+ $page = Page::query()->first()->forceFill([
+ 'markdown' => '',
+ 'html' => "<h1>Dogcat</h1><p class=\"callout info\">Some callout text</p><p>Another line</p>",
+ ]);
+ $page->save();
+
+ $resp = $this->asEditor()->get($page->getUrl('/export/markdown'));
+ $resp->assertSee("# Dogcat\n\n<p class=\"callout info\">Some callout text</p>\n\nAnother line");
+ }
+
+ public function test_page_markdown_export_handles_bookstacks_wysiwyg_codeblock_format()
+ {
+ $page = Page::query()->first()->forceFill([
+ 'markdown' => '',
+ 'html' => '<h1>Dogcat</h1>'."\r\n".'<pre id="bkmrk-var-a-%3D-%27cat%27%3B"><code class="language-JavaScript">var a = \'cat\';</code></pre><p>Another line</p>',
+ ]);
+ $page->save();
+
+ $resp = $this->asEditor()->get($page->getUrl('/export/markdown'));
+ $resp->assertSee("# Dogcat\n\n```JavaScript\nvar a = 'cat';\n```\n\nAnother line");
+ }
+
+ public function test_chapter_markdown_export()
+ {
+ $chapter = Chapter::query()->first();
+ $page = $chapter->pages()->first();
+ $resp = $this->asEditor()->get($chapter->getUrl('/export/markdown'));
+
+ $resp->assertSee('# ' . $chapter->name);
+ $resp->assertSee('# ' . $page->name);
+ }
+
+ public function test_book_markdown_export()
+ {
+ $book = Book::query()->whereHas('pages')->whereHas('chapters')->first();
+ $chapter = $book->chapters()->first();
+ $page = $chapter->pages()->first();
+ $resp = $this->asEditor()->get($book->getUrl('/export/markdown'));
+
+ $resp->assertSee('# ' . $book->name);
+ $resp->assertSee('# ' . $chapter->name);
+ $resp->assertSee('# ' . $page->name);
+ }
+
}
use BookStack\Entities\Tools\PageContent;
use BookStack\Entities\Models\Page;
use Tests\TestCase;
+use Tests\Uploads\UsesImages;
class PageContentTest extends TestCase
{
+ use UsesImages;
+
+ protected $base64Jpeg = '/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=';
public function test_page_includes()
{
- $page = Page::first();
- $secondPage = Page::where('id', '!=', $page->id)->first();
+ $page = Page::query()->first();
+ $secondPage = Page::query()->where('id', '!=', $page->id)->first();
$secondPage->html = "<p id='section1'>Hello, This is a test</p><p id='section2'>This is a second block of content</p>";
$secondPage->save();
public function test_saving_page_with_includes()
{
- $page = Page::first();
- $secondPage = Page::where('id', '!=', $page->id)->first();
+ $page = Page::query()->first();
+ $secondPage = Page::query()->where('id', '!=', $page->id)->first();
$this->asEditor();
$includeTag = '{{@' . $secondPage->id . '}}';
public function test_page_includes_do_not_break_tables()
{
- $page = Page::first();
- $secondPage = Page::where('id', '!=', $page->id)->first();
+ $page = Page::query()->first();
+ $secondPage = Page::query()->where('id', '!=', $page->id)->first();
$content = '<table id="table"><tbody><tr><td>test</td></tr></tbody></table>';
$secondPage->html = $content;
public function test_page_content_scripts_removed_by_default()
{
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
$script = 'abc123<script>console.log("hello-test")</script>abc123';
$page->html = "escape {$script}";
$page->save();
];
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
foreach ($checks as $check) {
$page->html = $check;
];
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
foreach ($checks as $check) {
$page->html = $check;
];
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
foreach ($checks as $check) {
$page->html = $check;
];
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
foreach ($checks as $check) {
$page->html = $check;
];
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
foreach ($checks as $check) {
$page->html = $check;
public function test_page_inline_on_attributes_removed_by_default()
{
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
$script = '<p onmouseenter="console.log(\'test\')">Hello</p>';
$page->html = "escape {$script}";
$page->save();
];
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
foreach ($checks as $check) {
$page->html = $check;
public function test_page_content_scripts_show_when_configured()
{
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
config()->push('app.allow_content_scripts', 'true');
$script = 'abc123<script>console.log("hello-test")</script>abc123';
public function test_page_inline_on_attributes_show_if_configured()
{
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
config()->push('app.allow_content_scripts', 'true');
$script = '<p onmouseenter="console.log(\'test\')">Hello</p>';
public function test_duplicate_ids_does_not_break_page_render()
{
$this->asEditor();
- $pageA = Page::first();
+ $pageA = Page::query()->first();
$pageB = Page::query()->where('id', '!=', $pageA->id)->first();
$content = '<ul id="bkmrk-xxx-%28"></ul> <ul id="bkmrk-xxx-%28"></ul>';
public function test_duplicate_ids_fixed_on_page_save()
{
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
$content = '<ul id="bkmrk-test"><li>test a</li><li><ul id="bkmrk-test"><li>test b</li></ul></li></ul>';
$pageSave = $this->put($page->getUrl(), [
]);
$pageSave->assertRedirect();
- $updatedPage = Page::where('id', '=', $page->id)->first();
+ $updatedPage = Page::query()->where('id', '=', $page->id)->first();
$this->assertEquals(substr_count($updatedPage->html, "bkmrk-test\""), 1);
}
public function test_anchors_referencing_non_bkmrk_ids_rewritten_after_save()
{
$this->asEditor();
- $page = Page::first();
+ $page = Page::query()->first();
$content = '<h1 id="non-standard-id">test</h1><p><a href="#non-standard-id">link</a></p>';
$this->put($page->getUrl(), [
'summary' => ''
]);
- $updatedPage = Page::where('id', '=', $page->id)->first();
+ $updatedPage = Page::query()->where('id', '=', $page->id)->first();
$this->assertStringContainsString('id="bkmrk-test"', $updatedPage->html);
$this->assertStringContainsString('href="#bkmrk-test"', $updatedPage->html);
}
$pageView = $this->get($page->getUrl());
$pageView->assertElementExists('.page-content p > s');
}
+
+ public function test_page_markdown_single_html_comment_saving()
+ {
+ $this->asEditor();
+ $page = Page::query()->first();
+
+ $content = '<!-- Test Comment -->';
+ $this->put($page->getUrl(), [
+ 'name' => $page->name, 'markdown' => $content,
+ 'html' => '', 'summary' => ''
+ ]);
+
+ $page->refresh();
+ $this->assertStringMatchesFormat($content, $page->html);
+
+ $pageView = $this->get($page->getUrl());
+ $pageView->assertStatus(200);
+ $pageView->assertSee($content);
+ }
+
+ public function test_base64_images_get_extracted_from_page_content()
+ {
+ $this->asEditor();
+ $page = Page::query()->first();
+
+ $this->put($page->getUrl(), [
+ 'name' => $page->name, 'summary' => '',
+ 'html' => '<p>test<img src="data:image/jpeg;base64,'.$this->base64Jpeg.'"/></p>',
+ ]);
+
+ $page->refresh();
+ $this->assertStringMatchesFormat('%A<p%A>test<img src="http://localhost/uploads/images/gallery/%A.jpeg">%A</p>%A', $page->html);
+
+ $matches = [];
+ preg_match('/src="https:\/\/p.rizon.top:443\/http\/localhost(.*?)"/', $page->html, $matches);
+ $imagePath = $matches[1];
+ $imageFile = public_path($imagePath);
+ $this->assertEquals(base64_decode($this->base64Jpeg), file_get_contents($imageFile));
+
+ $this->deleteImage($imagePath);
+ }
+
+ public function test_base64_images_get_extracted_when_containing_whitespace()
+ {
+ $this->asEditor();
+ $page = Page::query()->first();
+
+ $base64PngWithWhitespace = "iVBORw0KGg\noAAAANSUhE\tUgAAAAEAAAA BCA YAAAAfFcSJAAA\n\t ACklEQVR4nGMAAQAABQAB";
+ $base64PngWithoutWhitespace = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQAB';
+ $this->put($page->getUrl(), [
+ 'name' => $page->name, 'summary' => '',
+ 'html' => '<p>test<img src="data:image/png;base64,'.$base64PngWithWhitespace.'"/></p>',
+ ]);
+
+ $page->refresh();
+ $this->assertStringMatchesFormat('%A<p%A>test<img src="http://localhost/uploads/images/gallery/%A.png">%A</p>%A', $page->html);
+
+ $matches = [];
+ preg_match('/src="https:\/\/p.rizon.top:443\/http\/localhost(.*?)"/', $page->html, $matches);
+ $imagePath = $matches[1];
+ $imageFile = public_path($imagePath);
+ $this->assertEquals(base64_decode($base64PngWithoutWhitespace), file_get_contents($imageFile));
+
+ $this->deleteImage($imagePath);
+ }
+
+ public function test_base64_images_blanked_if_not_supported_extension_for_extract()
+ {
+ $this->asEditor();
+ $page = Page::query()->first();
+
+ $this->put($page->getUrl(), [
+ 'name' => $page->name, 'summary' => '',
+ 'html' => '<p>test<img src="data:image/jiff;base64,'.$this->base64Jpeg.'"/></p>',
+ ]);
+
+ $page->refresh();
+ $this->assertStringContainsString('<img src=""', $page->html);
+ }
}
class PageTest extends TestCase
{
+
+ public function test_page_view_when_creator_is_deleted_but_owner_exists()
+ {
+ $page = Page::query()->first();
+ $user = $this->getViewer();
+ $owner = $this->getEditor();
+ $page->created_by = $user->id;
+ $page->owned_by = $owner->id;
+ $page->save();
+ $user->delete();
+
+ $resp = $this->asAdmin()->get($page->getUrl());
+ $resp->assertStatus(200);
+ $resp->assertSeeText('Owned by ' . $owner->name);
+ }
+
public function test_page_creation_with_markdown_content()
{
$this->setSettings(['app-editor' => 'markdown']);
$redirectReq->assertNotificationContains('Page Successfully Deleted');
}
+ public function test_page_full_delete_removes_all_revisions()
+ {
+ /** @var Page $page */
+ $page = Page::query()->first();
+ $page->revisions()->create([
+ 'html' => '<p>ducks</p>',
+ 'name' => 'my page revision',
+ 'type' => 'draft',
+ ]);
+ $page->revisions()->create([
+ 'html' => '<p>ducks</p>',
+ 'name' => 'my page revision',
+ 'type' => 'revision',
+ ]);
+
+ $this->assertDatabaseHas('page_revisions', [
+ 'page_id' => $page->id,
+ ]);
+
+ $this->asEditor()->delete($page->getUrl());
+ $this->asAdmin()->post('/settings/recycle-bin/empty');
+
+ $this->assertDatabaseMissing('page_revisions', [
+ 'page_id' => $page->id,
+ ]);
+ }
+
public function test_page_copy()
{
$page = Page::first();
'book_id' => $newBook->id,
]);
}
+
+ public function test_empty_markdown_still_saves_without_error()
+ {
+ $this->setSettings(['app-editor' => 'markdown']);
+ $book = Book::query()->first();
+
+ $this->asEditor()->get($book->getUrl('/create-page'));
+ $draft = Page::query()->where('book_id', '=', $book->id)
+ ->where('draft', '=', true)->first();
+
+ $details = [
+ 'name' => 'my page',
+ 'markdown' => '',
+ ];
+ $resp = $this->post($book->getUrl("/draft/{$draft->id}"), $details);
+ $resp->assertRedirect();
+
+ $this->assertDatabaseHas('pages', [
+ 'markdown' => $details['markdown'],
+ 'id' => $draft->id,
+ 'draft' => false
+ ]);
+ }
}
\ No newline at end of file
<?php namespace Tests\Entity;
-use BookStack\Entities\Models\Book;
-use BookStack\Entities\Models\Chapter;
use BookStack\Actions\Tag;
use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\Page;
-use BookStack\Auth\Permissions\PermissionService;
-use Tests\BrowserKitTest;
+use Tests\TestCase;
-class TagTest extends BrowserKitTest
+class TagTest extends TestCase
{
protected $defaultTagCount = 20;
/**
* Get an instance of a page that has many tags.
- * @param \BookStack\Actions\Tag[]|bool $tags
- * @return Entity
*/
- protected function getEntityWithTags($class, $tags = false): Entity
+ protected function getEntityWithTags($class, ?array $tags = null): Entity
{
$entity = $class::first();
- if (!$tags) {
+ if (is_null($tags)) {
$tags = factory(Tag::class, $this->defaultTagCount)->make();
}
$attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'county']));
$attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'planet']));
$attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'plans']));
- $page = $this->getEntityWithTags(Page::class, $attrs);
+ $page = $this->getEntityWithTags(Page::class, $attrs->all());
- $this->asAdmin()->get('/ajax/tags/suggest/names?search=dog')->seeJsonEquals([]);
- $this->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country', 'county']);
- $this->get('/ajax/tags/suggest/names?search=cou')->seeJsonEquals(['country', 'county']);
- $this->get('/ajax/tags/suggest/names?search=pla')->seeJsonEquals(['planet', 'plans']);
+ $this->asAdmin()->get('/ajax/tags/suggest/names?search=dog')->assertExactJson([]);
+ $this->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country', 'county']);
+ $this->get('/ajax/tags/suggest/names?search=cou')->assertExactJson(['country', 'county']);
+ $this->get('/ajax/tags/suggest/names?search=pla')->assertExactJson(['planet', 'plans']);
}
public function test_tag_value_suggestions()
$attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'county', 'value' => 'dog']));
$attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'planet', 'value' => 'catapult']));
$attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'plans', 'value' => 'dodgy']));
- $page = $this->getEntityWithTags(Page::class, $attrs);
+ $page = $this->getEntityWithTags(Page::class, $attrs->all());
- $this->asAdmin()->get('/ajax/tags/suggest/values?search=ora')->seeJsonEquals([]);
- $this->get('/ajax/tags/suggest/values?search=cat')->seeJsonEquals(['cats', 'cattery', 'catapult']);
- $this->get('/ajax/tags/suggest/values?search=do')->seeJsonEquals(['dog', 'dodgy']);
- $this->get('/ajax/tags/suggest/values?search=cas')->seeJsonEquals(['castle']);
+ $this->asAdmin()->get('/ajax/tags/suggest/values?search=ora')->assertExactJson([]);
+ $this->get('/ajax/tags/suggest/values?search=cat')->assertExactJson(['cats', 'cattery', 'catapult']);
+ $this->get('/ajax/tags/suggest/values?search=do')->assertExactJson(['dog', 'dodgy']);
+ $this->get('/ajax/tags/suggest/values?search=cas')->assertExactJson(['castle']);
}
public function test_entity_permissions_effect_tag_suggestions()
{
- $permissionService = $this->app->make(PermissionService::class);
-
// Create some tags with similar names to test with and save to a page
$attrs = collect();
$attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'country']));
$attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'color']));
- $page = $this->getEntityWithTags(Page::class, $attrs);
+ $page = $this->getEntityWithTags(Page::class, $attrs->all());
- $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country']);
- $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country']);
+ $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country']);
+ $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country']);
// Set restricted permission the page
$page->restricted = true;
$page->save();
$page->rebuildPermissions();
- $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country']);
- $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals([]);
+ $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country']);
+ $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertExactJson([]);
+ }
+
+ public function test_tags_shown_on_search_listing()
+ {
+ $tags = [
+ factory(Tag::class)->make(['name' => 'category', 'value' => 'buckets']),
+ factory(Tag::class)->make(['name' => 'color', 'value' => 'red']),
+ ];
+
+ $page = $this->getEntityWithTags(Page::class, $tags);
+ $resp = $this->asEditor()->get("/search?term=[category]");
+ $resp->assertSee($page->name);
+ $resp->assertElementContains('[href="' . $page->getUrl() . '"]', 'category');
+ $resp->assertElementContains('[href="' . $page->getUrl() . '"]', 'buckets');
+ $resp->assertElementContains('[href="' . $page->getUrl() . '"]', 'color');
+ $resp->assertElementContains('[href="' . $page->getUrl() . '"]', 'red');
}
}
$this->assertCount(1, $handler->getRecords());
}
+
+ public function test_access_to_non_existing_image_location_provides_404_response()
+ {
+ $resp = $this->actingAs($this->getViewer())->get('/uploads/images/gallery/2021-05/anonexistingimage.png');
+ $resp->assertStatus(404);
+ $resp->assertSeeText('Image Not Found');
+ }
}
\ No newline at end of file
--- /dev/null
+<?php
+
+use BookStack\Actions\Favourite;
+use BookStack\Entities\Models\Book;
+use BookStack\Entities\Models\Bookshelf;
+use BookStack\Entities\Models\Chapter;
+use BookStack\Entities\Models\Page;
+use Tests\TestCase;
+
+class FavouriteTest extends TestCase
+{
+
+ public function test_page_add_favourite_flow()
+ {
+ $page = Page::query()->first();
+ $editor = $this->getEditor();
+
+ $resp = $this->actingAs($editor)->get($page->getUrl());
+ $resp->assertElementContains('button', 'Favourite');
+ $resp->assertElementExists('form[method="POST"][action$="/favourites/add"]');
+
+ $resp = $this->post('/favourites/add', [
+ 'type' => get_class($page),
+ 'id' => $page->id,
+ ]);
+ $resp->assertRedirect($page->getUrl());
+ $resp->assertSessionHas('success', "\"{$page->name}\" has been added to your favourites");
+
+ $this->assertDatabaseHas('favourites', [
+ 'user_id' => $editor->id,
+ 'favouritable_type' => $page->getMorphClass(),
+ 'favouritable_id' => $page->id,
+ ]);
+ }
+
+ public function test_page_remove_favourite_flow()
+ {
+ $page = Page::query()->first();
+ $editor = $this->getEditor();
+ Favourite::query()->forceCreate([
+ 'user_id' => $editor->id,
+ 'favouritable_id' => $page->id,
+ 'favouritable_type' => $page->getMorphClass(),
+ ]);
+
+ $resp = $this->actingAs($editor)->get($page->getUrl());
+ $resp->assertElementContains('button', 'Unfavourite');
+ $resp->assertElementExists('form[method="POST"][action$="/favourites/remove"]');
+
+ $resp = $this->post('/favourites/remove', [
+ 'type' => get_class($page),
+ 'id' => $page->id,
+ ]);
+ $resp->assertRedirect($page->getUrl());
+ $resp->assertSessionHas('success', "\"{$page->name}\" has been removed from your favourites");
+
+ $this->assertDatabaseMissing('favourites', [
+ 'user_id' => $editor->id,
+ ]);
+ }
+
+ public function test_book_chapter_shelf_pages_contain_favourite_button()
+ {
+ $entities = [
+ Bookshelf::query()->first(),
+ Book::query()->first(),
+ Chapter::query()->first(),
+ ];
+ $this->actingAs($this->getEditor());
+
+ foreach ($entities as $entity) {
+ $resp = $this->get($entity->getUrl());
+ $resp->assertElementExists('form[method="POST"][action$="/favourites/add"]');
+ }
+ }
+
+ public function test_header_contains_link_to_favourites_page_when_logged_in()
+ {
+ $this->setSettings(['app-public' => 'true']);
+ $this->get('/')->assertElementNotContains('header', 'My Favourites');
+ $this->actingAs($this->getViewer())->get('/')->assertElementContains('header a', 'My Favourites');
+ }
+
+ public function test_favourites_shown_on_homepage()
+ {
+ $editor = $this->getEditor();
+
+ $resp = $this->actingAs($editor)->get('/');
+ $resp->assertElementNotExists('#top-favourites');
+
+ /** @var Page $page */
+ $page = Page::query()->first();
+ $page->favourites()->save((new Favourite)->forceFill(['user_id' => $editor->id]));
+
+ $resp = $this->get('/');
+ $resp->assertElementExists('#top-favourites');
+ $resp->assertElementContains('#top-favourites', $page->name);
+ }
+
+ public function test_favourites_list_page_shows_favourites_and_has_working_pagination()
+ {
+ /** @var Page $page */
+ $page = Page::query()->first();
+ $editor = $this->getEditor();
+
+ $resp = $this->actingAs($editor)->get('/favourites');
+ $resp->assertDontSee($page->name);
+
+ $page->favourites()->save((new Favourite)->forceFill(['user_id' => $editor->id]));
+
+ $resp = $this->get('/favourites');
+ $resp->assertSee($page->name);
+
+ $resp = $this->get('/favourites?page=2');
+ $resp->assertDontSee($page->name);
+ }
+
+}
\ No newline at end of file
<?php namespace Tests;
+use BookStack\Auth\Role;
+use BookStack\Auth\User;
use BookStack\Entities\Models\Bookshelf;
+use BookStack\Entities\Models\Page;
class HomepageTest extends TestCase
{
$homeVisit->assertElementContains('.content-wrap', $shelf->name);
$homeVisit->assertElementContains('.content-wrap', $book->name);
}
+
+ public function test_new_users_dont_have_any_recently_viewed()
+ {
+ $user = factory(User::class)->create();
+ $viewRole = Role::getRole('Viewer');
+ $user->attachRole($viewRole);
+
+ $homeVisit = $this->actingAs($user)->get('/');
+ $homeVisit->assertElementContains('#recently-viewed', 'You have not viewed any pages');
+ }
}
--- /dev/null
+<?php namespace Tests;
+
+use BookStack\Entities\Models\Book;
+use BookStack\Entities\Models\Bookshelf;
+use BookStack\Entities\Models\Chapter;
+use BookStack\Entities\Models\Page;
+use BookStack\Entities\Repos\BookRepo;
+use BookStack\Entities\Repos\BookshelfRepo;
+use Illuminate\Support\Str;
+use Tests\Uploads\UsesImages;
+
+class OpenGraphTest extends TestCase
+{
+ use UsesImages;
+
+ public function test_page_tags()
+ {
+ $page = Page::query()->first();
+ $resp = $this->asEditor()->get($page->getUrl());
+ $tags = $this->getOpenGraphTags($resp);
+
+ $this->assertEquals($page->getShortName() . ' | BookStack', $tags['title']);
+ $this->assertEquals($page->getUrl(), $tags['url']);
+ $this->assertEquals(Str::limit($page->text, 100, '...'), $tags['description']);
+ }
+
+ public function test_chapter_tags()
+ {
+ $chapter = Chapter::query()->first();
+ $resp = $this->asEditor()->get($chapter->getUrl());
+ $tags = $this->getOpenGraphTags($resp);
+
+ $this->assertEquals($chapter->getShortName() . ' | BookStack', $tags['title']);
+ $this->assertEquals($chapter->getUrl(), $tags['url']);
+ $this->assertEquals(Str::limit($chapter->description, 100, '...'), $tags['description']);
+ }
+
+ public function test_book_tags()
+ {
+ $book = Book::query()->first();
+ $resp = $this->asEditor()->get($book->getUrl());
+ $tags = $this->getOpenGraphTags($resp);
+
+ $this->assertEquals($book->getShortName() . ' | BookStack', $tags['title']);
+ $this->assertEquals($book->getUrl(), $tags['url']);
+ $this->assertEquals(Str::limit($book->description, 100, '...'), $tags['description']);
+ $this->assertArrayNotHasKey('image', $tags);
+
+ // Test image set if image has cover image
+ $bookRepo = app(BookRepo::class);
+ $bookRepo->updateCoverImage($book, $this->getTestImage('image.png'));
+ $resp = $this->asEditor()->get($book->getUrl());
+ $tags = $this->getOpenGraphTags($resp);
+
+ $this->assertEquals($book->getBookCover(), $tags['image']);
+ }
+
+ public function test_shelf_tags()
+ {
+ $shelf = Bookshelf::query()->first();
+ $resp = $this->asEditor()->get($shelf->getUrl());
+ $tags = $this->getOpenGraphTags($resp);
+
+ $this->assertEquals($shelf->getShortName() . ' | BookStack', $tags['title']);
+ $this->assertEquals($shelf->getUrl(), $tags['url']);
+ $this->assertEquals(Str::limit($shelf->description, 100, '...'), $tags['description']);
+ $this->assertArrayNotHasKey('image', $tags);
+
+ // Test image set if image has cover image
+ $shelfRepo = app(BookshelfRepo::class);
+ $shelfRepo->updateCoverImage($shelf, $this->getTestImage('image.png'));
+ $resp = $this->asEditor()->get($shelf->getUrl());
+ $tags = $this->getOpenGraphTags($resp);
+
+ $this->assertEquals($shelf->getBookCover(), $tags['image']);
+ }
+
+ /**
+ * Parse the open graph tags from a test response.
+ */
+ protected function getOpenGraphTags(TestResponse $resp): array
+ {
+ $tags = [];
+
+ libxml_use_internal_errors(true);
+ $doc = new \DOMDocument();
+ $doc->loadHTML($resp->getContent());
+ $metaElems = $doc->getElementsByTagName('meta');
+ /** @var \DOMElement $elem */
+ foreach ($metaElems as $elem) {
+ $prop = $elem->getAttribute('property');
+ $name = explode(':', $prop)[1] ?? null;
+ if ($name) {
+ $tags[$name] = $elem->getAttribute('content');
+ }
+ }
+
+ return $tags;
+ }
+
+
+}
\ No newline at end of file
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Page;
+use Illuminate\Support\Facades\View;
class PublicActionTest extends TestCase
{
public function test_content_not_listed_on_404_for_public_users()
{
$page = Page::query()->first();
+ $page->fill(['name' => 'my testing random unique page name'])->save();
$this->asAdmin()->get($page->getUrl()); // Fake visit to show on recents
$resp = $this->get('/cats/dogs/hippos');
$resp->assertStatus(404);
$resp->assertSee($page->name);
+ View::share('pageTitle', '');
Auth::logout();
$resp = $this->get('/cats/dogs/hippos');
return $user;
}
+ /**
+ * Get a user that's not a system user such as the guest user.
+ */
+ public function getNormalUser()
+ {
+ return User::query()->where('system_name', '=', null)->get()->last();
+ }
+
/**
* Regenerate the permission for an entity.
*/
<?php namespace Tests;
-use BookStack\Auth\Access\SocialAuthService;
use BookStack\Auth\User;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Tools\PageContent;
$this->setSettings(['registration-enabled' => 'true']);
$user = factory(User::class)->make();
- $this->post('/register', ['email' => $user->email, 'name' => $user->name, 'password' => 'password']);
+ $this->post('/register', ['email' => $user->email, 'name' => $user->name, 'password' => 'password']);
$this->assertCount(2, $args);
$this->assertEquals('standard', $args[0]);
$loginResp->assertSee('Super Cat Name');
}
+
+ public function test_add_social_driver_allows_a_configure_for_redirect_callback_to_be_passed()
+ {
+ Theme::addSocialDriver(
+ 'discord',
+ [
+ 'client_id' => 'abc123',
+ 'client_secret' => 'def456',
+ 'name' => 'Super Cat Name',
+ ],
+ 'SocialiteProviders\Discord\DiscordExtendSocialite@handle',
+ function ($driver) {
+ $driver->with(['donkey' => 'donut']);
+ }
+ );
+
+ $loginResp = $this->get('/login/service/discord');
+ $redirect = $loginResp->headers->get('location');
+ $this->assertStringContainsString('donkey=donut', $redirect);
+ }
+
+
protected function usingThemeFolder(callable $callback)
{
// Create a folder and configure a theme
$this->checkEnvConfigResult('APP_URL', '', 'session.path', '/');
}
+ public function test_saml2_idp_authn_context_string_parsed_as_space_separated_array()
+ {
+ $this->checkEnvConfigResult(
+ 'SAML2_IDP_AUTHNCONTEXT',
+ 'urn:federation:authentication:windows urn:federation:authentication:linux',
+ 'saml2.onelogin.security.requestedAuthnContext',
+ ['urn:federation:authentication:windows', 'urn:federation:authentication:linux']
+ );
+ }
+
/**
* Set an environment variable of the given name and value
* then check the given config key to see if it matches the given result.
* Providing a null $envVal clears the variable.
+ * @param mixed $expectedResult
*/
- protected function checkEnvConfigResult(string $envName, ?string $envVal, string $configKey, string $expectedResult)
+ protected function checkEnvConfigResult(string $envName, ?string $envVal, string $configKey, $expectedResult)
{
$this->runWithEnv($envName, $envVal, function() use ($configKey, $expectedResult) {
$this->assertEquals($expectedResult, config($configKey));
use BookStack\Entities\Repos\PageRepo;
use BookStack\Uploads\Attachment;
use BookStack\Entities\Models\Page;
-use BookStack\Auth\Permissions\PermissionService;
use BookStack\Uploads\AttachmentService;
use Illuminate\Http\UploadedFile;
use Tests\TestCase;
-use Tests\TestResponse;
class AttachmentTest extends TestCase
{
public function test_file_upload()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asAdmin();
$admin = $this->getAdmin();
$fileName = 'upload_test_file.txt';
public function test_file_upload_does_not_use_filename()
{
- $page = Page::first();
+ $page = Page::query()->first();
$fileName = 'upload_test_file.txt';
public function test_file_display_and_access()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asAdmin();
$fileName = 'upload_test_file.txt';
public function test_attaching_link_to_page()
{
- $page = Page::first();
+ $page = Page::query()->first();
$admin = $this->getAdmin();
$this->asAdmin();
public function test_attachment_updating()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asAdmin();
$attachment = $this->createAttachment($page);
public function test_file_deletion()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asAdmin();
$fileName = 'deletion_test.txt';
$this->uploadFile($fileName, $page->id);
public function test_attachment_deletion_on_page_deletion()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asAdmin();
$fileName = 'deletion_test.txt';
$this->uploadFile($fileName, $page->id);
{
$admin = $this->getAdmin();
$viewer = $this->getViewer();
- $page = Page::first(); /** @var Page $page */
+ $page = Page::query()->first(); /** @var Page $page */
$this->actingAs($admin);
$fileName = 'permission_test.txt';
public function test_data_and_js_links_cannot_be_attached_to_a_page()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asAdmin();
$badLinks = [
]);
}
}
+
+ public function test_file_access_with_open_query_param_provides_inline_response_with_correct_content_type()
+ {
+ $page = Page::query()->first();
+ $this->asAdmin();
+ $fileName = 'upload_test_file.txt';
+
+ $upload = $this->uploadFile($fileName, $page->id);
+ $upload->assertStatus(200);
+ $attachment = Attachment::query()->orderBy('id', 'desc')->take(1)->first();
+
+ $attachmentGet = $this->get($attachment->getUrl(true));
+ // http-foundation/Response does some 'fixing' of responses to add charsets to text responses.
+ $attachmentGet->assertHeader('Content-Type', 'text/plain; charset=UTF-8');
+ $attachmentGet->assertHeader('Content-Disposition', "inline; filename=\"upload_test_file.txt\"");
+
+ $this->deleteUploads();
+ }
}
public function test_image_upload()
{
- $page = Page::first();
+ $page = Page::query()->first();
$admin = $this->getAdmin();
$this->actingAs($admin);
public function test_image_display_thumbnail_generation_does_not_increase_image_size()
{
- $page = Page::first();
+ $page = Page::query()->first();
$admin = $this->getAdmin();
$this->actingAs($admin);
public function test_image_usage()
{
- $page = Page::first();
+ $page = Page::query()->first();
$editor = $this->getEditor();
$this->actingAs($editor);
public function test_php_files_cannot_be_uploaded()
{
- $page = Page::first();
+ $page = Page::query()->first();
$admin = $this->getAdmin();
$this->actingAs($admin);
public function test_php_like_files_cannot_be_uploaded()
{
- $page = Page::first();
+ $page = Page::query()->first();
$admin = $this->getAdmin();
$this->actingAs($admin);
];
foreach ($badNames as $name) {
$galleryFile = $this->getTestImage($name);
- $page = Page::first();
+ $page = Page::query()->first();
$badPath = $this->getTestImagePath('gallery', $name);
$this->deleteImage($badPath);
config()->set('filesystems.images', 'local_secure');
$this->asEditor();
$galleryFile = $this->getTestImage('my-secure-test-upload.png');
- $page = Page::first();
+ $page = Page::query()->first();
$expectedPath = storage_path('uploads/images/gallery/' . Date('Y-m') . '/my-secure-test-upload.png');
$upload = $this->call('POST', '/images/gallery', ['uploaded_to' => $page->id], [], ['file' => $galleryFile], []);
config()->set('filesystems.images', 'local_secure');
$this->asEditor();
$galleryFile = $this->getTestImage('my-secure-test-upload.png');
- $page = Page::first();
+ $page = Page::query()->first();
$expectedPath = storage_path('uploads/images/gallery/' . Date('Y-m') . '/my-secure-test-upload.png');
$upload = $this->call('POST', '/images/gallery', ['uploaded_to' => $page->id], [], ['file' => $galleryFile], []);
public function test_image_delete()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asAdmin();
$imageName = 'first-image.png';
$relPath = $this->getTestImagePath('gallery', $imageName);
public function test_image_delete_does_not_delete_similar_images()
{
- $page = Page::first();
+ $page = Page::query()->first();
$this->asAdmin();
$imageName = 'first-image.png';
public function test_deleted_unused_images()
{
- $page = Page::first();
+ $page = Page::query()->first();
$admin = $this->getAdmin();
$this->actingAs($admin);