Compare commits

...

63 Commits

Author SHA1 Message Date
Dan Brown
4f16129869 Updated version for release v0.26.3 2019-07-10 20:21:22 +01:00
Dan Brown
64a8037fdd Merge branch 'v0.26' into release 2019-07-10 20:19:54 +01:00
Dan Brown
c732970f6e Hardened page content script escaping
Increased range of tests to cover.

Fixes #1531
2019-07-10 20:17:22 +01:00
Dan Brown
7502ba1bc8 Updated version and assets for release v0.26.2 2019-05-27 13:48:20 +01:00
Dan Brown
33a04697ef Merge branch 'master' into release 2019-05-27 13:47:47 +01:00
Dan Brown
a602cdf401 Fixed some body card horizontal scroll and column collapse issues
As mentoined in #1441
2019-05-27 13:10:48 +01:00
Dan Brown
5aa741cb60 Prevented tri-layout sidebars being faded on mobile
As mentoined in #1441
2019-05-27 12:56:31 +01:00
Dan Brown
3ad1b42a74 Updated page delete to handle inactive custom homepage correctly
Fixes #1447
2019-05-27 12:40:19 +01:00
Dan Brown
2b7362fa94 Added highlighting to current book-tree item
Related to #1435
2019-05-25 16:52:44 +01:00
Dan Brown
35f35bcba5 Updated custom home views to use tri-layout
Closes #1423
2019-05-25 16:35:27 +01:00
Dan Brown
13c0386e84 Updated string functions to use mulitbyte versions where needed
Fixes #816
2019-05-25 16:15:19 +01:00
Dan Brown
78f5f44460 Updated page navigation click to show content tab on mobile
Fixes #1454
2019-05-25 15:37:49 +01:00
Dan Brown
35e6635379 Fixed chapter description not showing in book exports
Closes #1465
2019-05-25 15:21:02 +01:00
Dan Brown
8ae35f645a Fixed faulty baseUrl rewrites
Fixes #1452
May help #1377
2019-05-19 16:25:05 +01:00
Dan Brown
5470a9e035 Merge branch 'kostefun-patch-1' 2019-05-19 15:43:11 +01:00
Dan Brown
dbfe63ccf6 Fixed missing comma in RU translation array 2019-05-19 15:42:46 +01:00
Dan Brown
114f10d5ca Merge branch 'patch-1' of git://github.com/kostefun/BookStack into kostefun-patch-1 2019-05-19 15:41:48 +01:00
Dan Brown
5226ddd959 Merge pull request #1446 from kostefun/patch-5
Update common.php
2019-05-19 15:41:21 +01:00
Dan Brown
60013f776a Merge branch 'master' into patch-5 2019-05-19 15:40:54 +01:00
Dan Brown
ac0a070fc8 Merge pull request #1445 from kostefun/patch-4
Update entities.php
2019-05-19 15:40:15 +01:00
Dan Brown
b05659d7a3 Merge pull request #1443 from kostefun/patch-3
Update common.php
2019-05-19 15:39:48 +01:00
Dan Brown
3af4648dc3 Merge pull request #1437 from NootoNooto/patch-2
Added Dutch translations for some new texts
2019-05-19 15:36:05 +01:00
Dan Brown
e1e1ea6099 Amended page save button layout to fix z-index issues
- Added a new mobile save button instead of trying to reposition the
original.
- Also recuced the point where the editor top toolbar will collapse to
become x-scrollable.

Fixes #1424
2019-05-19 15:30:58 +01:00
Dan Brown
0c3dc50cd9 Added mobile search bar on search page
Since the header one hides on mobile devices.
Fixes #1450
2019-05-19 15:06:52 +01:00
Dan Brown
0a0ceb382e Doubled image upload display thumb size
Related to #1108
2019-05-19 14:52:17 +01:00
Dan Brown
896f88174a Updated page navigation logic to ignore empty headers
Fixes #1429
2019-05-15 21:02:11 +01:00
Dan Brown
0ee9e5c4db Updated both editors to ignore image paste if text data apparent
Designed to ignore image data when copying from a spreadsheet.
Fixes #987
2019-05-15 20:23:09 +01:00
kostefun
112f73c91c Update settings.php
Ru locale fix
2019-05-14 17:50:23 +07:00
kostefun
b47dc046e0 Update common.php 2019-05-13 17:40:09 +07:00
kostefun
215d84d705 Update entities.php 2019-05-13 17:31:19 +07:00
kostefun
c459d86b58 Update common.php 2019-05-13 17:21:05 +07:00
kostefun
adf0d5fce2 Update settings.php 2019-05-13 17:09:50 +07:00
Nooto
cb355c8aad Modified Bookshelf texts 2019-05-08 23:57:44 +02:00
Nooto
d0e351b942 Added translations for Bookshelves 2019-05-08 23:51:34 +02:00
Nooto
e3d570e928 Update activities.php 2019-05-08 23:25:13 +02:00
Nooto
e00c170d85 Update common.php 2019-05-08 23:24:22 +02:00
Nooto
e430dad38c Added translations for View All, Copy, Reply, etc 2019-05-08 23:05:30 +02:00
Dan Brown
b70a5c0cdb Updated version and assets for release v0.26.1 2019-05-07 23:05:47 +01:00
Dan Brown
9443ae9f40 Merge branch 'master' into release 2019-05-07 23:05:10 +01:00
Dan Brown
d62d2384cb Updated guest settings system to format value as per non-guest
Fixes #1431
2019-05-07 22:56:48 +01:00
Dan Brown
a981dc41cb Merge pull request #1433 from Hambern/master
Updated the Swedish language files
2019-05-07 22:45:42 +01:00
Dan Brown
97ffbaa740 Fixed issue where books titles could be leaked via shelf home view
- Also added test to cover
Fixes #1425
2019-05-07 22:42:48 +01:00
vagrant
8051558d3a Updated the Swedish language files 2019-05-07 21:29:30 +00:00
Dan Brown
7ef059e254 Fixed some editor image/drawing upload endpoints
Fixes #1428
2019-05-07 22:23:44 +01:00
Dan Brown
4329fee2c9 Fixed 404 card header fonts
Fixes #1427
2019-05-07 22:10:54 +01:00
Dan Brown
b1cf5ab309 Standardised login tab order and evened card padding
Closes #1418
2019-05-07 22:07:50 +01:00
Dan Brown
b67d9f4036 Updated verison for 0.26 dev path 2019-05-07 21:55:41 +01:00
Dan Brown
224d9e7a7d Merge pull request #1420 from moucho/master
Spanish translation
2019-05-07 21:52:02 +01:00
Dan Brown
31419c3913 Merge pull request #1419 from Mant1kor/master
Ukrainian translation update
2019-05-07 21:51:15 +01:00
moucho
ba36d36597 Spanish 2019-05-07 01:28:00 +02:00
Mantikor
ac7d6b8737 Update validation.php 2019-05-06 23:11:23 +03:00
Mantikor
e52dab825a Update settings.php 2019-05-06 23:05:48 +03:00
Mantikor
33f51d5b78 Update passwords.php 2019-05-06 22:27:17 +03:00
Mantikor
ae7529376b Update pagination.php 2019-05-06 22:26:43 +03:00
Mantikor
aefd4d423c Update errors.php 2019-05-06 22:25:40 +03:00
Mantikor
bad44391d4 Update auth.php 2019-05-06 22:21:29 +03:00
Mantikor
1880633be3 Update common.php 2019-05-06 22:21:15 +03:00
Mantikor
8273f8b16e Update entities.php 2019-05-06 22:20:31 +03:00
Mantikor
0600f752eb Update components.php 2019-05-06 21:57:22 +03:00
Mantikor
342dc8948c Update common.php 2019-05-06 21:56:10 +03:00
Mantikor
3e24e44106 Update auth.php 2019-05-06 21:45:16 +03:00
Mantikor
404d11d0eb Update activities.php 2019-05-06 21:40:04 +03:00
Mantikor
07b889547d Merge pull request #1 from BookStackApp/master
merge changes
2019-05-06 21:33:09 +03:00
71 changed files with 928 additions and 424 deletions

View File

@@ -216,12 +216,12 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
*/
public function getShortName($chars = 8)
{
if (strlen($this->name) <= $chars) {
if (mb_strlen($this->name) <= $chars) {
return $this->name;
}
$splitName = explode(' ', $this->name);
if (strlen($splitName[0]) <= $chars) {
if (mb_strlen($splitName[0]) <= $chars) {
return $splitName[0];
}

View File

@@ -49,7 +49,7 @@ class CreateAdmin extends Command
if (empty($email)) {
$email = $this->ask('Please specify an email address for the new admin user');
}
if (strlen($email) < 5 || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
if (mb_strlen($email) < 5 || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
return $this->error('Invalid email address provided');
}
@@ -61,7 +61,7 @@ class CreateAdmin extends Command
if (empty($name)) {
$name = $this->ask('Please specify an name for the new admin user');
}
if (strlen($name) < 2) {
if (mb_strlen($name) < 2) {
return $this->error('Invalid name provided');
}
@@ -69,7 +69,7 @@ class CreateAdmin extends Command
if (empty($password)) {
$password = $this->secret('Please specify a password for the new admin user');
}
if (strlen($password) < 5) {
if (mb_strlen($password) < 5) {
return $this->error('Invalid password provided, Must be at least 5 characters');
}

View File

@@ -104,7 +104,7 @@ class Book extends Entity
public function getExcerpt(int $length = 100)
{
$description = $this->description;
return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description;
return mb_strlen($description) > $length ? mb_substr($description, 0, $length-3) . '...' : $description;
}
/**

View File

@@ -83,7 +83,7 @@ class Bookshelf extends Entity
public function getExcerpt(int $length = 100)
{
$description = $this->description;
return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description;
return mb_strlen($description) > $length ? mb_substr($description, 0, $length-3) . '...' : $description;
}
/**

View File

@@ -56,7 +56,7 @@ class Chapter extends Entity
public function getExcerpt(int $length = 100)
{
$description = $this->text ?? $this->description;
return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description;
return mb_strlen($description) > $length ? mb_substr($description, 0, $length-3) . '...' : $description;
}
/**

View File

@@ -760,13 +760,13 @@ class EntityRepo
$xPath = new DOMXPath($doc);
// Remove standard script tags
$scriptElems = $xPath->query('//body//*//script');
$scriptElems = $xPath->query('//script');
foreach ($scriptElems as $scriptElem) {
$scriptElem->parentNode->removeChild($scriptElem);
}
// Remove 'on*' attributes
$onAttributes = $xPath->query('//body//*/@*[starts-with(name(), \'on\')]');
$onAttributes = $xPath->query('//@*[starts-with(name(), \'on\')]');
foreach ($onAttributes as $attr) {
/** @var \DOMAttr $attr*/
$attrName = $attr->nodeName;
@@ -852,10 +852,13 @@ class EntityRepo
*/
public function destroyPage(Page $page)
{
// Check if set as custom homepage
// Check if set as custom homepage & remove setting if not used or throw error if active
$customHome = setting('app-homepage', '0:');
if (intval($page->id) === intval(explode(':', $customHome)[0])) {
throw new NotifyException(trans('errors.page_custom_home_deletion'), $page->getUrl());
if (setting('app-homepage-type') === 'page') {
throw new NotifyException(trans('errors.page_custom_home_deletion'), $page->getUrl());
}
setting()->remove('app-homepage');
}
$this->destroyEntityCommonRelations($page);

View File

@@ -192,7 +192,7 @@ class PageRepo extends EntityRepo
// Create an unique id for the element
// Uses the content as a basis to ensure output is the same every time
// the same content is passed through.
$contentId = 'bkmrk-' . substr(strtolower(preg_replace('/\s+/', '-', trim($element->nodeValue))), 0, 20);
$contentId = 'bkmrk-' . mb_substr(strtolower(preg_replace('/\s+/', '-', trim($element->nodeValue))), 0, 20);
$newId = urlencode($contentId);
$loopIndex = 0;
@@ -422,25 +422,29 @@ class PageRepo extends EntityRepo
return [];
}
$tree = collect([]);
foreach ($headers as $header) {
$text = $header->nodeValue;
$tree->push([
$tree = collect($headers)->map(function($header) {
$text = trim(str_replace("\xc2\xa0", '', $header->nodeValue));
if (mb_strlen($text) > 30) {
$text = mb_substr($text, 0, 27) . '...';
}
return [
'nodeName' => strtolower($header->nodeName),
'level' => intval(str_replace('h', '', $header->nodeName)),
'link' => '#' . $header->getAttribute('id'),
'text' => strlen($text) > 30 ? substr($text, 0, 27) . '...' : $text
]);
}
'text' => $text,
];
})->filter(function($header) {
return mb_strlen($header['text']) > 0;
});
// Normalise headers if only smaller headers have been used
if (count($tree) > 0) {
$minLevel = $tree->pluck('level')->min();
$tree = $tree->map(function ($header) use ($minLevel) {
$header['level'] -= ($minLevel - 2);
return $header;
});
}
$minLevel = $tree->pluck('level')->min();
$tree = $tree->map(function ($header) use ($minLevel) {
$header['level'] -= ($minLevel - 2);
return $header;
});
return $tree->toArray();
}

View File

@@ -142,7 +142,7 @@ class RegisterController extends Controller
if ($registrationRestrict) {
$restrictedEmailDomains = explode(',', str_replace(' ', '', $registrationRestrict));
$userEmailDomain = $domain = substr(strrchr($userData['email'], "@"), 1);
$userEmailDomain = $domain = mb_substr(mb_strrchr($userData['email'], "@"), 1);
if (!in_array($userEmailDomain, $restrictedEmailDomains)) {
throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), '/register');
}

View File

@@ -67,6 +67,9 @@ class HomeController extends Controller
if ($homepageOption === 'bookshelves') {
$shelves = $this->entityRepo->getAllPaginated('bookshelf', 18, $commonData['sort'], $commonData['order']);
foreach ($shelves as $shelf) {
$shelf->books = $this->entityRepo->getBookshelfChildren($shelf);
}
$data = array_merge($commonData, ['shelves' => $shelves]);
return view('common.home-shelves', $data);
}

View File

@@ -4,10 +4,8 @@ use Illuminate\Contracts\Cache\Repository as Cache;
/**
* Class SettingService
*
* The settings are a simple key-value database store.
*
* @package BookStack\Services
* For non-authenticated users, user settings are stored via the session instead.
*/
class SettingService
{
@@ -52,6 +50,19 @@ class SettingService
return $formatted;
}
/**
* Get a value from the session instead of the main store option.
* @param $key
* @param bool $default
* @return mixed
*/
protected function getFromSession($key, $default = false)
{
$value = session()->get($key, $default);
$formatted = $this->formatValue($value, $default);
return $formatted;
}
/**
* Get a user-specific setting from the database or cache.
* @param \BookStack\Auth\User $user
@@ -62,7 +73,7 @@ class SettingService
public function getUser($user, $key, $default = false)
{
if ($user->isDefault()) {
return session()->get($key, $default);
return $this->getFromSession($key, $default);
}
return $this->get($this->userKey($user->id, $key), $default);
}

View File

@@ -230,7 +230,7 @@ class ImageRepo
{
$image->thumbs = [
'gallery' => $this->getThumbnail($image, 150, 150, false),
'display' => $this->getThumbnail($image, 840, null, true)
'display' => $this->getThumbnail($image, 1680, null, true)
];
}

View File

@@ -123,10 +123,11 @@ function baseUrl($path, $forceAppDomain = false)
// Remove non-specified domain if forced and we have a domain
if ($isFullUrl && $forceAppDomain) {
if (!empty($base) && strpos($path, $base) === 0) {
$path = trim(substr($path, strlen($base) - 1));
$path = mb_substr($path, mb_strlen($base));
} else {
$explodedPath = explode('/', $path);
$path = implode('/', array_splice($explodedPath, 3));
}
$explodedPath = explode('/', $path);
$path = implode('/', array_splice($explodedPath, 3));
}
// Return normal url path if not specified in config
@@ -134,7 +135,7 @@ function baseUrl($path, $forceAppDomain = false)
return url($path);
}
return $base . '/' . $path;
return $base . '/' . ltrim($path, '/');
}
/**

12
public/dist/app.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -628,6 +628,54 @@ li.checkbox-item, li.task-list-item {
.text-right {
text-align: right; }
@media screen and (min-width: 360px) {
.text-xxs-center {
text-align: center; }
.text-xxs-left {
text-align: left; }
.text-xxs-right {
text-align: right; } }
@media screen and (min-width: 400px) {
.text-xs-center {
text-align: center; }
.text-xs-left {
text-align: left; }
.text-xs-right {
text-align: right; } }
@media screen and (min-width: 600px) {
.text-s-center {
text-align: center; }
.text-s-left {
text-align: left; }
.text-s-right {
text-align: right; } }
@media screen and (min-width: 880px) {
.text-m-center {
text-align: center; }
.text-m-left {
text-align: left; }
.text-m-right {
text-align: right; } }
@media screen and (min-width: 1000px) {
.text-l-center {
text-align: center; }
.text-l-left {
text-align: left; }
.text-l-right {
text-align: right; } }
@media screen and (min-width: 1100px) {
.text-xl-center {
text-align: center; }
.text-xl-left {
text-align: left; }
.text-xl-right {
text-align: right; } }
.text-bigger {
font-size: 1.1em; }
@@ -714,7 +762,7 @@ span.sep {
grid-row-gap: 0; }
@media screen and (max-width: 880px) {
.grid.third {
.grid.third:not(.no-break) {
grid-template-columns: 1fr 1fr; }
.grid.half:not(.no-break), .grid.left-focus:not(.no-break), .grid.right-focus:not(.no-break) {
grid-template-columns: 1fr; }
@@ -729,7 +777,7 @@ span.sep {
order: 1; } }
@media screen and (max-width: 600px) {
.grid.third {
.grid.third:not(.no-break) {
grid-template-columns: 1fr; } }
@media screen and (max-width: 400px) {
@@ -914,9 +962,6 @@ body.flexbox {
.tri-layout-container .tri-layout-left-contents, .tri-layout-container .tri-layout-right-contents {
padding-left: 16px;
padding-right: 16px; }
.tri-layout-container .tri-layout-right-contents > div, .tri-layout-container .tri-layout-left-contents > div {
opacity: 0.6;
z-index: 0; }
.tri-layout-container .tri-layout-left > *, .tri-layout-container .tri-layout-right > * {
display: none;
pointer-events: none; }
@@ -946,19 +991,18 @@ body.flexbox {
@media screen and (min-width: 1000px) {
.tri-layout-mobile-tabs {
display: none; } }
display: none; }
.tri-layout-left-contents > div, .tri-layout-right-contents > div {
opacity: 0.6;
transition: opacity ease-in-out 120ms; }
.tri-layout-left-contents > div:hover, .tri-layout-right-contents > div:hover {
opacity: 1; } }
@media screen and (max-width: 880px) {
.tri-layout-container {
margin-left: 0;
margin-right: 0; } }
.tri-layout-left-contents > div, .tri-layout-right-contents > div {
opacity: 0.6;
transition: opacity ease-in-out 120ms; }
.tri-layout-left-contents > div:hover, .tri-layout-right-contents > div:hover {
opacity: 1; }
/**
* Callouts
*/
@@ -1108,7 +1152,7 @@ body.flexbox {
margin-left: auto;
margin-right: auto;
margin-bottom: 32px;
overflow: auto;
overflow: initial;
min-height: 60vh; }
.content-wrap.card.auto-height {
min-height: 0; }
@@ -1117,7 +1161,7 @@ body.flexbox {
@media screen and (max-width: 1400px) {
.content-wrap.card {
padding: 24px 32px; } }
padding: 16px 32px; } }
@media screen and (max-width: 880px) {
.content-wrap.card {
@@ -1125,7 +1169,7 @@ body.flexbox {
@media screen and (max-width: 600px) {
.content-wrap.card {
padding: 16px 12px; } }
padding: 16px 16px; } }
/**
* Tags
@@ -1961,11 +2005,15 @@ header .search-box {
padding-right: 0; }
.book-tree .sidebar-page-list .entity-list-item {
padding-top: 3px;
padding-bottom: 3px; }
padding-bottom: 3px;
background-clip: content-box;
border-radius: 0 3px 3px 0; }
.book-tree .sidebar-page-list .entity-list-item .content {
padding-top: 6px;
padding-bottom: 6px;
max-width: calc(100% - 20px); }
.book-tree .sidebar-page-list .entity-list-item.selected {
background-color: rgba(0, 0, 0, 0.08); }
.book-tree .sidebar-page-list .entity-list-item.no-hover {
margin-top: -6px;
padding-right: 0; }
@@ -2342,33 +2390,31 @@ ul.pagination {
.page-editor .mce-top-part::before {
box-shadow: none; }
@media screen and (max-width: 880px) {
@media screen and (max-width: 600px) {
.page-edit-toolbar {
overflow-x: scroll;
overflow-y: visible;
z-index: 12; }
overflow-y: visible; }
.page-edit-toolbar .grid.third {
display: block;
white-space: nowrap; }
.page-edit-toolbar .grid.third > div {
display: inline-block; } }
@media screen and (max-width: 880px) {
.page-edit-toolbar #save-button {
position: fixed;
z-index: 30;
border-radius: 50%;
width: 56px;
height: 56px;
font-size: 24px;
right: 16px;
bottom: 12px;
box-shadow: 0 2px 2px 1px rgba(0, 0, 0, 0.13);
background-color: currentColor; }
.page-edit-toolbar #save-button svg {
fill: #FFF; }
.page-edit-toolbar #save-button span {
display: none; } }
.page-save-mobile-button {
position: fixed;
z-index: 30;
border-radius: 50%;
width: 56px;
height: 56px;
font-size: 24px;
right: 16px;
bottom: 12px;
box-shadow: 0 2px 2px 1px rgba(0, 0, 0, 0.13);
background-color: currentColor;
text-align: center; }
.page-save-mobile-button svg {
fill: #FFF;
margin-right: 0; }
.draft-notification {
pointer-events: none;

116
public/dist/styles.css vendored
View File

@@ -665,6 +665,54 @@ li.checkbox-item, li.task-list-item {
.text-right {
text-align: right; }
@media screen and (min-width: 360px) {
.text-xxs-center {
text-align: center; }
.text-xxs-left {
text-align: left; }
.text-xxs-right {
text-align: right; } }
@media screen and (min-width: 400px) {
.text-xs-center {
text-align: center; }
.text-xs-left {
text-align: left; }
.text-xs-right {
text-align: right; } }
@media screen and (min-width: 600px) {
.text-s-center {
text-align: center; }
.text-s-left {
text-align: left; }
.text-s-right {
text-align: right; } }
@media screen and (min-width: 880px) {
.text-m-center {
text-align: center; }
.text-m-left {
text-align: left; }
.text-m-right {
text-align: right; } }
@media screen and (min-width: 1000px) {
.text-l-center {
text-align: center; }
.text-l-left {
text-align: left; }
.text-l-right {
text-align: right; } }
@media screen and (min-width: 1100px) {
.text-xl-center {
text-align: center; }
.text-xl-left {
text-align: left; }
.text-xl-right {
text-align: right; } }
.text-bigger {
font-size: 1.1em; }
@@ -815,7 +863,7 @@ span.sep {
grid-row-gap: 0; }
@media screen and (max-width: 880px) {
.grid.third {
.grid.third:not(.no-break) {
grid-template-columns: 1fr 1fr; }
.grid.half:not(.no-break), .grid.left-focus:not(.no-break), .grid.right-focus:not(.no-break) {
grid-template-columns: 1fr; }
@@ -830,7 +878,7 @@ span.sep {
order: 1; } }
@media screen and (max-width: 600px) {
.grid.third {
.grid.third:not(.no-break) {
grid-template-columns: 1fr; } }
@media screen and (max-width: 400px) {
@@ -1015,9 +1063,6 @@ body.flexbox {
.tri-layout-container .tri-layout-left-contents, .tri-layout-container .tri-layout-right-contents {
padding-left: 16px;
padding-right: 16px; }
.tri-layout-container .tri-layout-right-contents > div, .tri-layout-container .tri-layout-left-contents > div {
opacity: 0.6;
z-index: 0; }
.tri-layout-container .tri-layout-left > *, .tri-layout-container .tri-layout-right > * {
display: none;
pointer-events: none; }
@@ -1047,19 +1092,18 @@ body.flexbox {
@media screen and (min-width: 1000px) {
.tri-layout-mobile-tabs {
display: none; } }
display: none; }
.tri-layout-left-contents > div, .tri-layout-right-contents > div {
opacity: 0.6;
transition: opacity ease-in-out 120ms; }
.tri-layout-left-contents > div:hover, .tri-layout-right-contents > div:hover {
opacity: 1; } }
@media screen and (max-width: 880px) {
.tri-layout-container {
margin-left: 0;
margin-right: 0; } }
.tri-layout-left-contents > div, .tri-layout-right-contents > div {
opacity: 0.6;
transition: opacity ease-in-out 120ms; }
.tri-layout-left-contents > div:hover, .tri-layout-right-contents > div:hover {
opacity: 1; }
/**
* Callouts
*/
@@ -1209,7 +1253,7 @@ body.flexbox {
margin-left: auto;
margin-right: auto;
margin-bottom: 32px;
overflow: auto;
overflow: initial;
min-height: 60vh; }
.content-wrap.card.auto-height {
min-height: 0; }
@@ -1218,7 +1262,7 @@ body.flexbox {
@media screen and (max-width: 1400px) {
.content-wrap.card {
padding: 24px 32px; } }
padding: 16px 32px; } }
@media screen and (max-width: 880px) {
.content-wrap.card {
@@ -1226,7 +1270,7 @@ body.flexbox {
@media screen and (max-width: 600px) {
.content-wrap.card {
padding: 16px 12px; } }
padding: 16px 16px; } }
/**
* Tags
@@ -3492,11 +3536,15 @@ header .search-box {
padding-right: 0; }
.book-tree .sidebar-page-list .entity-list-item {
padding-top: 3px;
padding-bottom: 3px; }
padding-bottom: 3px;
background-clip: content-box;
border-radius: 0 3px 3px 0; }
.book-tree .sidebar-page-list .entity-list-item .content {
padding-top: 6px;
padding-bottom: 6px;
max-width: calc(100% - 20px); }
.book-tree .sidebar-page-list .entity-list-item.selected {
background-color: rgba(0, 0, 0, 0.08); }
.book-tree .sidebar-page-list .entity-list-item.no-hover {
margin-top: -6px;
padding-right: 0; }
@@ -3873,33 +3921,31 @@ ul.pagination {
.page-editor .mce-top-part::before {
box-shadow: none; }
@media screen and (max-width: 880px) {
@media screen and (max-width: 600px) {
.page-edit-toolbar {
overflow-x: scroll;
overflow-y: visible;
z-index: 12; }
overflow-y: visible; }
.page-edit-toolbar .grid.third {
display: block;
white-space: nowrap; }
.page-edit-toolbar .grid.third > div {
display: inline-block; } }
@media screen and (max-width: 880px) {
.page-edit-toolbar #save-button {
position: fixed;
z-index: 30;
border-radius: 50%;
width: 56px;
height: 56px;
font-size: 24px;
right: 16px;
bottom: 12px;
box-shadow: 0 2px 2px 1px rgba(0, 0, 0, 0.13);
background-color: currentColor; }
.page-edit-toolbar #save-button svg {
fill: #FFF; }
.page-edit-toolbar #save-button span {
display: none; } }
.page-save-mobile-button {
position: fixed;
z-index: 30;
border-radius: 50%;
width: 56px;
height: 56px;
font-size: 24px;
right: 16px;
bottom: 12px;
box-shadow: 0 2px 2px 1px rgba(0, 0, 0, 0.13);
background-color: currentColor;
text-align: center; }
.page-save-mobile-button svg {
fill: #FFF;
margin-right: 0; }
.draft-notification {
pointer-events: none;

View File

@@ -180,9 +180,20 @@ class MarkdownEditor {
// Handle image paste
cm.on('paste', (cm, event) => {
if (!event.clipboardData || !event.clipboardData.items) return;
for (let i = 0; i < event.clipboardData.items.length; i++) {
uploadImage(event.clipboardData.items[i].getAsFile());
const clipboardItems = event.clipboardData.items;
if (!event.clipboardData || !clipboardItems) return;
// Don't handle if clipboard includes text content
for (let clipboardItem of clipboardItems) {
if (clipboardItem.type.includes('text/')) {
return;
}
}
for (let clipboardItem of clipboardItems) {
if (clipboardItem.type.includes("image")) {
uploadImage(clipboardItem.getAsFile());
}
}
});
@@ -298,7 +309,7 @@ class MarkdownEditor {
formData.append('file', file, remoteFilename);
formData.append('uploaded_to', context.pageId);
window.$http.post('/images/gallery/upload', formData).then(resp => {
window.$http.post('/images/gallery', formData).then(resp => {
const newContent = `[![${selectedText}](${resp.data.thumbs.display})](${resp.data.url})`;
replaceContent(placeHolderText, newContent);
}).catch(err => {
@@ -366,7 +377,7 @@ class MarkdownEditor {
uploaded_to: Number(document.getElementById('page-editor').getAttribute('page-id'))
};
window.$http.post(window.baseUrl('/images/drawing/upload'), data).then(resp => {
window.$http.post(window.baseUrl('/images/drawio'), data).then(resp => {
this.insertDrawing(resp.data, cursorPos);
DrawIO.close();
}).catch(err => {
@@ -402,7 +413,7 @@ class MarkdownEditor {
uploaded_to: Number(document.getElementById('page-editor').getAttribute('page-id'))
};
window.$http.post(window.baseUrl(`/images/drawing/upload`), data).then(resp => {
window.$http.post(window.baseUrl(`/images/drawio`), data).then(resp => {
let newText = `<div drawio-diagram="${resp.data.id}"><img src="${resp.data.url}"></div>`;
let newContent = this.cm.getValue().split('\n').map(line => {
if (line.indexOf(`drawio-diagram="${drawingId}"`) !== -1) {

View File

@@ -20,6 +20,7 @@ class PageDisplay {
// Sidebar page nav click event
$('.sidebar-page-nav').on('click', 'a', event => {
window.components['tri-layout'][0].showContent();
this.goToText(event.target.getAttribute('href').substr(1));
});
}

View File

@@ -66,28 +66,44 @@ class TriLayout {
*/
mobileTabClick(event) {
const tab = event.target.getAttribute('tri-layout-mobile-tab');
this.showTab(tab);
}
/**
* Show the content tab.
* Used by the page-display component.
*/
showContent() {
this.showTab('content');
}
/**
* Show the given tab
* @param tabName
*/
showTab(tabName) {
this.scrollCache[this.lastTabShown] = document.documentElement.scrollTop;
// Set tab status
const activeTabs = document.querySelectorAll('.tri-layout-mobile-tab.active');
for (let tab of activeTabs) {
tab.classList.remove('active');
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);
}
event.target.classList.add('active');
// Toggle section
const showInfo = (tab === 'info');
const showInfo = (tabName === 'info');
this.elem.classList.toggle('show-info', showInfo);
// Set the scroll position from cache
const pageHeader = document.querySelector('header');
const defaultScrollTop = pageHeader.getBoundingClientRect().bottom;
document.documentElement.scrollTop = this.scrollCache[tab] || defaultScrollTop;
document.documentElement.scrollTop = this.scrollCache[tabName] || defaultScrollTop;
setTimeout(() => {
document.documentElement.scrollTop = this.scrollCache[tab] || defaultScrollTop;
document.documentElement.scrollTop = this.scrollCache[tabName] || defaultScrollTop;
}, 50);
this.lastTabShown = tab;
this.lastTabShown = tabName;
}
}

View File

@@ -8,11 +8,20 @@ import DrawIO from "../services/drawio";
* @param editor
*/
function editorPaste(event, editor, wysiwygComponent) {
if (!event.clipboardData || !event.clipboardData.items) return;
const clipboardItems = event.clipboardData.items;
if (!event.clipboardData || !clipboardItems) return;
for (let clipboardItem of event.clipboardData.items) {
if (clipboardItem.type.indexOf("image") === -1) continue;
event.preventDefault();
// Don't handle if clipboard includes text content
for (let clipboardItem of clipboardItems) {
if (clipboardItem.type.includes('text/')) {
return;
}
}
for (let clipboardItem of clipboardItems) {
if (!clipboardItem.type.includes("image")) {
continue;
}
const id = "image-" + Math.random().toString(16).slice(2);
const loadingImage = window.baseUrl('/loading.gif');
@@ -53,7 +62,7 @@ async function uploadImageFile(file, wysiwygComponent) {
formData.append('file', file, remoteFilename);
formData.append('uploaded_to', wysiwygComponent.pageId);
const resp = await window.$http.post(window.baseUrl('/images/gallery/upload'), formData);
const resp = await window.$http.post(window.baseUrl('/images/gallery'), formData);
return resp.data;
}

View File

@@ -181,7 +181,7 @@
margin-left: auto;
margin-right: auto;
margin-bottom: $-xl;
overflow: auto;
overflow: initial;
min-height: 60vh;
&.auto-height {
min-height: 0;
@@ -192,7 +192,7 @@
}
@include smaller-than($xxl) {
.content-wrap.card {
padding: $-l $-xl;
padding: $-m $-xl;
}
}
@include smaller-than($m) {
@@ -202,7 +202,7 @@
}
@include smaller-than($s) {
.content-wrap.card {
padding: $-m $-s;
padding: $-m $-m;
}
}

View File

@@ -59,7 +59,7 @@
}
@include smaller-than($m) {
.grid.third {
.grid.third:not(.no-break) {
grid-template-columns: 1fr 1fr;
}
.grid.half:not(.no-break), .grid.left-focus:not(.no-break), .grid.right-focus:not(.no-break) {
@@ -81,7 +81,7 @@
}
@include smaller-than($s) {
.grid.third {
.grid.third:not(.no-break) {
grid-template-columns: 1fr;
}
}
@@ -257,10 +257,6 @@ body.flexbox {
padding-left: $-m;
padding-right: $-m;
}
.tri-layout-right-contents > div, .tri-layout-left-contents > div {
opacity: 0.6;
z-index: 0;
}
.tri-layout-left > *, .tri-layout-right > * {
display: none;
pointer-events: none;
@@ -298,6 +294,13 @@ body.flexbox {
.tri-layout-mobile-tabs {
display: none;
}
.tri-layout-left-contents > div, .tri-layout-right-contents > div {
opacity: 0.6;
transition: opacity ease-in-out 120ms;
&:hover {
opacity: 1;
}
}
}
@include smaller-than($m) {
@@ -305,12 +308,4 @@ body.flexbox {
margin-left: 0;
margin-right: 0;
}
}
.tri-layout-left-contents > div, .tri-layout-right-contents > div {
opacity: 0.6;
transition: opacity ease-in-out 120ms;
&:hover {
opacity: 1;
}
}

View File

@@ -164,15 +164,21 @@
padding-left: 1rem;
padding-right: 0;
}
.entity-list-item {
padding-top: $-xxs;
padding-bottom: $-xxs;
background-clip: content-box;
border-radius: 0 3px 3px 0;
.content {
padding-top: $-xs;
padding-bottom: $-xs;
max-width: calc(100% - 20px);
}
}
.entity-list-item.selected {
background-color: rgba(0, 0, 0, 0.08);
}
.entity-list-item.no-hover {
margin-top: -$-xs;
padding-right: 0;

View File

@@ -20,11 +20,10 @@
}
}
@include smaller-than($m) {
@include smaller-than($s) {
.page-edit-toolbar {
overflow-x: scroll;
overflow-y: visible;
z-index: 12;
}
.page-edit-toolbar .grid.third {
display: block;
@@ -35,24 +34,21 @@
}
}
@include smaller-than($m) {
.page-edit-toolbar #save-button {
position: fixed;
z-index: 30;
border-radius: 50%;
width: 56px;
height: 56px;
font-size: 24px;
right: $-m;
bottom: $-s;
box-shadow: $bs-hover;
background-color: currentColor;
svg {
fill: #FFF;
}
span {
display: none;
}
.page-save-mobile-button {
position: fixed;
z-index: 30;
border-radius: 50%;
width: 56px;
height: 56px;
font-size: 24px;
right: $-m;
bottom: $-s;
box-shadow: $bs-hover;
background-color: currentColor;
text-align: center;
svg {
fill: #FFF;
margin-right: 0;
}
}

View File

@@ -291,15 +291,27 @@ li.checkbox-item, li.task-list-item {
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
@each $sizeLetter, $size in $screen-sizes {
@include larger-than($size) {
.text-#{$sizeLetter}-center {
text-align: center;
}
.text-#{$sizeLetter}-left {
text-align: left;
}
.text-#{$sizeLetter}-right {
text-align: right;
}
}
}
.text-bigger {
font-size: 1.1em;
}

View File

@@ -26,6 +26,8 @@ return [
'remember_me' => 'Recordarme',
'ldap_email_hint' => 'Por favor introduzca un mail para utilizar con esta cuenta.',
'create_account' => 'Crear una Cuenta',
'already_have_account' => '¿Ya tienes una cuenta?',
'dont_have_account' => '¿No tienes una cuenta?',
'social_login' => 'Login Social',
'social_registration' => 'Registro Social',
'social_registration_text' => 'Registrar y entrar utilizando otro servicio.',

View File

@@ -11,6 +11,7 @@ return [
'save' => 'Guardar',
'continue' => 'Continuar',
'select' => 'Seleccionar',
'toggle_all' => 'Marcarlos todos',
'more' => 'Más',
// Form Labels
@@ -23,6 +24,7 @@ return [
// Actions
'actions' => 'Acciones',
'view' => 'Ver',
'view_all' => 'Ver todos',
'create' => 'Crear',
'update' => 'Actualizar',
'edit' => 'Editar',
@@ -37,6 +39,11 @@ return [
'remove' => 'Remover',
'add' => 'Añadir',
// Sort Options
'sort_name' => 'Nombre',
'sort_created_at' => 'Fecha de Creación',
'sort_updated_at' => 'Fecha de Modificación',
// Misc
'deleted_user' => 'Usuario borrado',
'no_activity' => 'Ninguna actividad para mostrar',
@@ -53,7 +60,11 @@ return [
'view_profile' => 'Ver Perfil',
'edit_profile' => 'Editar Perfil',
// Layout tabs
'tab_info' => 'Información',
'tab_content' => 'Contenido',
// 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:',
'email_rights' => 'Todos los derechos reservados',
];
];

View File

@@ -11,6 +11,7 @@ return [
'recently_updated_pages' => 'Páginas recientemente actualizadas',
'recently_created_chapters' => 'Capítulos recientemente creados',
'recently_created_books' => 'Libros recientemente creados',
'recently_created_shelves' => 'Estantes recientemente creados',
'recently_update' => 'Recientemente actualizado',
'recently_viewed' => 'Recientemente visto',
'recent_activity' => 'Actividad reciente',
@@ -67,11 +68,13 @@ return [
// Shelves
'shelf' => 'Estante',
'shelves' => 'Estantes',
'x_shelves' => ':count estante|:count estantes',
'shelves_long' => 'Estantes',
'shelves_empty' => 'No hay estantes creados',
'shelves_create' => 'Crear estante',
'shelves_popular' => 'Estantes populares',
'shelves_new' => 'Estantes nuevos',
'shelves_new_action' => 'Nuevo estante',
'shelves_popular_empty' => 'Los estantes más populares aparecerán aquí.',
'shelves_new_empty' => 'Los libros más recientes aparecerán aquí.',
'shelves_save' => 'Guardar estante',
@@ -102,6 +105,7 @@ return [
'books_popular' => 'Libros populares',
'books_recent' => 'Libros recientes',
'books_new' => 'Libros nuevos',
'books_new_action' => 'Nuevo Libro',
'books_popular_empty' => 'Los libros más populares aparecerán aquí.',
'books_new_empty' => 'Los libros más recientes aparecerán aquí.',
'books_create' => 'Crear nuevo libro',
@@ -117,7 +121,6 @@ return [
'books_permissions_updated' => 'Permisos del libro actualizados',
'books_empty_contents' => 'Ninguna página o capítulo ha sido creada para este libro.',
'books_empty_create_page' => 'Crear una nueva página',
'books_empty_or' => 'ó',
'books_empty_sort_current_book' => 'Organizar el libro actual',
'books_empty_add_chapter' => 'Agregar un capítulo',
'books_permissions_active' => 'Permisos de libro activos',
@@ -125,6 +128,11 @@ return [
'books_navigation' => 'Navegación de libro',
'books_sort' => 'Organizar contenido de libro',
'books_sort_named' => 'Organizar libro :bookName',
'books_sort_name' => 'Organizar por Nombre',
'books_sort_created' => 'Organizar por Fecha de creación',
'books_sort_updated' => 'Organizar por Fecha de modificación',
'books_sort_chapters_first' => 'Capítulos al inicio',
'books_sort_chapters_last' => 'Capítulos al final ',
'books_sort_show_other' => 'Mostrar otros libros',
'books_sort_save' => 'Guardar nuevo orden',
@@ -202,6 +210,8 @@ return [
'pages_revisions_created_by' => 'Creado por',
'pages_revisions_date' => 'Fecha de revisión',
'pages_revisions_number' => '#',
'pages_revisions_numbered' => 'Revisión #:id',
'pages_revisions_numbered_changes' => 'Revisión #:id Cambios',
'pages_revisions_changelog' => 'Log de cambios',
'pages_revisions_changes' => 'Cambios',
'pages_revisions_current' => 'Versión actual',
@@ -267,6 +277,7 @@ return [
'profile_not_created_pages' => ':userName no ha creado ninguna página',
'profile_not_created_chapters' => ':userName no ha creado ningún capítulo',
'profile_not_created_books' => ':userName no ha creado ningún libro',
'profile_not_created_shelves' => ':userName no ha creado ningún estante',
// Comments
'comment' => 'Comentario',
@@ -288,6 +299,7 @@ return [
// Revision
'revision_delete_confirm' => '¿Está seguro de que desea eliminar esta revisión?',
'revision_restore_confirm' => '¿Está seguro de que desea restaurar esta revisión? El contenido actual de la página será reemplazado.',
'revision_delete_success' => 'Revisión eliminada',
'revision_cannot_delete_latest' => 'No se puede eliminar la última revisión.'
];

View File

@@ -64,6 +64,7 @@ return [
'role_cannot_be_edited' => 'Este rol no puede ser editado',
'role_system_cannot_be_deleted' => 'Este rol es un rol de sistema y no puede ser borrado',
'role_registration_default_cannot_delete' => 'Este rol no puede ser borrado mientras sea el rol por defecto de nuevos registros',
'role_cannot_remove_only_admin' => 'Este usuario es el único usuario asignado al rol de administrador. Asigna primero este rol a otro usuario antes de eliminarlo.',
// Comments
'comment_list' => 'Se ha producido un error al buscar los comentarios.',

View File

@@ -12,34 +12,44 @@ return [
'settings_save_success' => 'Ajustes guardados',
// App Settings
'app_settings' => 'Ajustes de la aplicación',
'app_customization' => 'Personalización',
'app_features_security' => 'Características & Seguridad',
'app_name' => 'Nombre de la aplicación',
'app_name_desc' => 'Este nombre se muestra en la cabecera y en cualquier correo electrónico',
'app_name_header' => '¿Mostrar el nombre de la aplicación en la cabecera?',
'app_public_viewing' => '¿Permitir vista pública?',
'app_secure_images' => '¿Habilitar mayor seguridad para subir imágenes?',
'app_name_header' => 'Mostrar el nombre de la aplicación en la cabecera',
'app_public_access' => 'Acceso Público',
'app_public_access_desc' => 'Activando esta opción permitirá que usuarios sin iniciar sesión puedan ver el contenido de tu aplicación Bookstack.',
'app_public_access_desc_guest' => 'El acceso público para visitantes puede ser controlado a través del usuario "Guest".',
'app_public_access_toggle' => 'Permitir acceso público',
'app_public_viewing' => '¿Permitir acceso público?',
'app_secure_images' => 'Mayor seguridad para subir imágenes',
'app_secure_images_toggle' => 'Habilitar mayor seguridad en la subida de imágenes',
'app_secure_images_desc' => 'Por razones de rendimiento, todas las imágenes son públicas. Esta opción agrega una cadena de texto larga difícil de adivinar. Asegúrese que los índices de directorio no están habilitados para evitar el acceso fácil a las imágenes.',
'app_editor' => 'Editor de páginas',
'app_editor' => 'Editor de Páginas',
'app_editor_desc' => 'Seleccione qué editor se usará por todos los usuarios para editar páginas.',
'app_custom_html' => 'Contenido de cabecera HTML personalizado',
'app_custom_html_desc' => 'Cualquier contenido agregado aquí será insertado al final de la sección <head> de cada página. Esto es útil para sobreescribir estilos o agregar código para analíticas web.',
'app_logo' => 'Logo de la aplicación',
'app_logo' => 'Logo de la Aplicación',
'app_logo_desc' => 'Esta imagen debería de ser 43px de altura. <br> Las imágenes grandes serán escaladas.',
'app_primary_color' => 'Color primario de la aplicación',
'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 restaurar al valor por defecto.',
'app_homepage' => 'Página de inicio',
'app_homepage_desc' => 'Elija la vista que se mostrará en la página de inicio en lugar de la vista predeterminada. Se ignorarán los permisos de la página seleccionada.',
'app_homepage_select' => 'Elija una página',
'app_disable_comments' => 'Deshabilitar comentarios',
'app_disable_comments_desc' => 'Deshabilita los comentarios en todas las páginas de la aplicación. Los comentarios existentes no se muestran.',
'app_disable_comments' => 'Deshabilitar Comentarios',
'app_disable_comments_toggle' => 'Deshabilitar comentarios',
'app_disable_comments_desc' => 'Deshabilita los comentarios en todas las páginas de la aplicación. <br> Los comentarios existentes no se muestran.',
// Registration Settings
'reg_settings' => 'Ajustes de registro',
'reg_allow' => '¿Permitir registro?',
'reg_settings' => 'Registro',
'reg_enable' => 'Habilitar Registro',
'reg_enable_toggle' => 'Habilitar registro',
'reg_enable_desc' => 'Cuando se habilita el registro los usuarios podrán registrarse como usuarios de la aplicación. Al registrarse se les asigna un rol único por defecto.',
'reg_default_role' => 'Rol de usuario por defecto después del registro',
'reg_confirm_email' => '¿Requerir correo electrónico de confirmaación?',
'reg_confirm_email_desc' => 'Si se emplea la restricción por dominio, entonces se requerirá la confirmación por correo electrónico y el valor a continuación será ignorado.',
'reg_confirm_restrict_domain' => 'Restringir registro al dominio',
'reg_email_confirmation' => 'Confirmación por Email',
'reg_email_confirmation_toggle' => 'Requerir confirmación por Email',
'reg_confirm_email_desc' => 'Si se emplea la restricción por dominio, entonces se requerirá la confirmación por correo electrónico y esta opción será ignorada.',
'reg_confirm_restrict_domain' => 'Restricción de Dominio',
'reg_confirm_restrict_domain_desc' => 'Introduzca una lista separada por comas de los dominio a los que les gustaría restringir el registro de usuarios. A los usuarios les será enviado un correo electrónico para confirmar la dirección antes de que se le permita interactuar con la aplicación. <br> Tenga en cuenta que los usuarios podrán cambiar sus direcciones de correo electrónico después de registrarse exitosamente.',
'reg_confirm_restrict_domain_placeholder' => 'Ninguna restricción establecida',
@@ -88,12 +98,19 @@ return [
// Users
'users' => 'Usuarios',
'user_profile' => 'Perfil de usuario',
'users_add_new' => 'Agregar nuevo usuario',
'user_profile' => 'Perfil de Usuario',
'users_add_new' => 'Agregar Nuevo Usuario',
'users_details' => 'Detalles de Usuario',
'users_details_desc' => 'Ajusta un nombre público y email para este usuario. El email será empleado para acceder a la aplicación.',
'users_details_desc_no_email' => 'Ajusta un nombre público para este usuario para que pueda ser reconocido por otros.',
'users_search' => 'Buscar usuarios',
'users_role' => 'Roles de usuario',
'users_role_desc' => 'Selecciona los roles a los que será asignado este usuario. Si se asignan varios roles los permisos se acumularán y recibirá todas las habilidades de los roles asignados.',
'users_password' => 'Contraseña de Usuario',
'users_password_desc' => 'Ajusta una contraseña que se utilizará para acceder a la aplicación. Debe ser al menos de 5 caracteres de longitud.',
'users_external_auth_id' => 'ID externo de autenticación',
'users_password_warning' => 'Solo debe rellenar este campo si desea cambiar su contraseña:',
'users_external_auth_id_desc' => 'Esta es la ID usada para asociar este usuario con LDAP.',
'users_password_warning' => 'Solo debe rellenar este campo si desea cambiar su contraseña.',
'users_system_public' => 'Este usuario representa cualquier usuario invitado que visita la aplicación. No puede utilizarse para acceder pero es asignado automáticamente.',
'users_delete' => 'Borrar usuario',
'users_delete_named' => 'Borrar usuario :userName',
@@ -104,8 +121,9 @@ return [
'users_edit_profile' => 'Editar perfil',
'users_edit_success' => 'Usuario actualizado',
'users_avatar' => 'Avatar del usuario',
'users_avatar_desc' => 'Esta imagen debe ser aproximadamente de 256px por lado.',
'users_avatar_desc' => 'Elige una imagen para representar a este usuario. Debe ser aproximadamente de 256px por lado.',
'users_preferred_language' => 'Idioma preferido',
'users_preferred_language_desc' => 'Esta opción cambiará el idioma de la interfaz de usuario en la aplicación. No afectará al contenido creado por los usuarios.',
'users_social_accounts' => 'Cuentas sociales',
'users_social_accounts_info' => 'Aquí puede conectar sus otras cuentas para un acceso rápido y fácil a la aplicación. Desconectando una cuenta aquí no revoca accesos ya autorizados. Revoque el acceso desde los ajustes de perfil en la cuenta social conectada.',
'users_social_connect' => 'Conectar cuenta',

View File

@@ -33,6 +33,7 @@ return [
'filled' => 'El campo :attribute es requerido.',
'exists' => 'El :attribute seleccionado es inválido.',
'image' => 'El :attribute debe ser una imagen.',
'image_extension' => 'El :attribute debe tener una extensión de imagen válida y soportada.',
'in' => 'El selected :attribute es inválio.',
'integer' => 'El :attribute debe ser un entero.',
'ip' => 'El :attribute debe ser una dirección IP válida.',
@@ -49,6 +50,7 @@ return [
'string' => 'El :attribute debe ser al menos :min caracteres.',
'array' => 'El :attribute debe tener como mínimo :min items.',
],
'no_double_extension' => 'El :attribute solo debe tener una extensión de archivo.',
'not_in' => 'El :attribute seleccionado es inválio.',
'numeric' => 'El :attribute debe ser numérico.',
'regex' => 'El formato de :attribute es inválido',
@@ -69,6 +71,7 @@ return [
'timezone' => 'El atributo :attribute debe ser una zona válida.',
'unique' => 'El atributo :attribute ya ha sido tomado.',
'url' => 'El atributo :attribute tiene un formato inválido.',
'uploaded' => 'El archivo no ha podido subirse. Es posible que el servidor no acepte archivos de este tamaño.',
// Custom validation lines
'custom' => [

View File

@@ -36,6 +36,14 @@ return [
'book_delete_notification' => 'Boek Succesvol Verwijderd',
'book_sort' => 'sorteerde boek',
'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_delete' => 'verwijderde boekenplank',
'bookshelf_delete_notification' => 'Boekenplank Succesvol Verwijderd',
// Other
'commented_on' => 'reactie op',

View File

@@ -1,35 +1,35 @@
<?php
return [
/**
* Buttons
*/
// Buttons
'cancel' => 'Annuleren',
'confirm' => 'Bevestigen',
'back' => 'Terug',
'save' => 'Opslaan',
'continue' => 'Doorgaan',
'select' => 'Kies',
'toggle_all' => 'Toggle Alles',
'more' => 'Meer',
/**
* Form Labels
*/
// Form Labels
'name' => 'Naam',
'description' => 'Beschrijving',
'role' => 'Rol',
'cover_image' => 'Omslagfoto',
'cover_image_description' => 'Deze afbeelding moet ongeveer 300x170px zijn.',
/**
* Actions
*/
// Actions
'actions' => 'Acties',
'view' => 'Bekijk',
'view_all' => 'Bekijk Alle',
'create' => 'Aanmaken',
'update' => 'Update',
'edit' => 'Bewerk',
'sort' => 'Sorteer',
'move' => 'Verplaats',
'copy' => 'Kopiëren',
'reply' => 'Beantwoorden',
'delete' => 'Verwijder',
'search' => 'Zoek',
'search_clear' => 'Zoekopdracht wissen',
@@ -37,15 +37,22 @@ return [
'remove' => 'Verwijderen',
'add' => 'Toevoegen',
/**
* Misc
*/
// Sort Options
'sort_name' => 'Naam',
'sort_created_at' => 'Aanmaakdatum',
'sort_updated_at' => 'Gewijzigd op',
// Misc
'deleted_user' => 'Verwijderde gebruiker',
'no_activity' => 'Geen activiteiten',
'no_items' => 'Geen items beschikbaar',
'back_to_top' => 'Terug naar boven',
'toggle_details' => 'Details Weergeven',
'toggle_thumbnails' => 'Thumbnails Weergeven',
'details' => 'Details',
'grid_view' => 'Grid weergave',
'list_view' => 'Lijst weergave',
'default' => 'Standaard',
/**
* Header
@@ -53,9 +60,13 @@ return [
'view_profile' => 'Profiel Weergeven',
'edit_profile' => 'Profiel Bewerken',
// Layout tabs
'tab_info' => 'Info',
'tab_content' => 'Inhoud',
/**
* Email Content
*/
'email_action_help' => 'Als je de knop ":actionText" niet werkt, kopieer en plak de onderstaande URL in je web browser:',
'email_rights' => 'Alle rechten voorbehouden',
];
];

View File

@@ -65,16 +65,45 @@ return [
'search_set_date' => 'Zet datum',
'search_update' => 'Update zoekresultaten',
/**
* Books
*/
// Shelves
'shelf' => 'Boekenplank',
'shelves' => 'Boekenplanken',
'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_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_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_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_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',
// Books
'book' => 'Boek',
'books' => 'Boeken',
'x_books' => ':count Boek|:count 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' => 'Nieuwe Boeken',
'books_popular_empty' => 'De meest populaire boeken worden hier weergegeven.',
'books_create' => 'Nieuw Boek Aanmaken',
'books_delete' => 'Boek Verwijderen',

View File

@@ -26,6 +26,7 @@ return [
*/
'actions' => 'Действия',
'view' => 'Просмотр',
'view_all' => 'Показать все',
'create' => 'Создание',
'update' => 'Обновление',
'edit' => 'Редактировать',
@@ -39,6 +40,11 @@ return [
'reset' => 'Сбросить',
'remove' => 'Удалить',
'add' => 'Добавить',
// Sort Options
'sort_name' => 'По имени',
'sort_created_at' => 'По дате создания',
'sort_updated_at' => 'По дате обновления',
/**
* Misc
@@ -46,18 +52,23 @@ return [
'deleted_user' => 'Удаленный пользователь',
'no_activity' => 'Нет действий для просмотра',
'no_items' => 'Нет доступных элементов',
'back_to_top' => 'Вернуться наверх',
'back_to_top' => 'Наверх',
'toggle_details' => 'Подробности',
'toggle_thumbnails' => 'Миниатюры',
'details' => 'Детали',
'grid_view' => 'Вид сеткой',
'list_view' => 'Вид списком',
'default' => 'По умолчанию',
/**
* Header
*/
'view_profile' => 'Просмотреть профиль',
'edit_profile' => 'Редактировать профиль',
// Layout tabs
'tab_info' => 'Информация',
'tab_content' => 'Содержание',
/**
* Email Content

View File

@@ -105,11 +105,13 @@ return [
*/
'shelf' => 'Полка',
'shelves' => 'Полки',
'x_shelves' => ':count полок|:count полок',
'shelves_long' => 'Книжные полки',
'shelves_empty' => 'Полки не созданы',
'shelves_create' => 'Создать новую полку',
'shelves_popular' => 'Популярные полки',
'shelves_new' => 'Новые полки',
'shelves_new_action' => 'Новая полка',
'shelves_popular_empty' => 'Популярные полки появятся здесь.',
'shelves_new_empty' => 'Последние созданные полки появятся здесь.',
'shelves_save' => 'Сохранить полку',

View File

@@ -1,77 +1,73 @@
<?php
/**
* Settings text strings
* Contains all text strings used in the general settings sections of BookStack
* including users and roles.
*/
return [
/**
* Settings text strings
* Contains all text strings used in the general settings sections of BookStack
* including users and roles.
*/
// Common Messages
'settings' => 'Настройки',
'settings_save' => 'Сохранить настройки',
'settings_save_success' => 'Настройки сохранены',
/**
* App settings
*/
'app_settings' => 'Настройки приложения',
// App Settings
'app_customization' => 'Настройки',
'app_features_security' => 'Функции & Безопасность',
'app_name' => 'Имя приложения',
'app_name_desc' => 'Это имя отображается в заголовке и в любых письмах.',
'app_name_header' => 'Показать имя приложения в заголовке?',
'app_name_desc' => 'Имя отображается в заголовке email отправленных системой.',
'app_name_header' => 'Отображать имя приложения в заголовке',
'app_public_access' => 'Публичный доступ',
'app_public_access_desc' => 'Включение этой опции позволит неавторизованным посетителям получить доступ к содержимому вашего BookStack.',
'app_public_access_desc_guest' => 'Публичный доступ контролируется через настройки пользователя "Guest"',
'app_public_access_toggle' => 'Разрешить публичный доступ',
'app_public_viewing' => 'Разрешить публичный просмотр?',
'app_secure_images' => 'Включить загрузку изображений с повышенной безопасностью?',
'app_secure_images_desc' => 'Из соображений производительности все изображения являются общедоступными. Этот параметр добавляет случайную сложную строку перед образами изображений. Убедитесь, что индексация каталогов не включена, чтобы предотвратить к ним легкий доступ.',
'app_secure_images' => 'Загрузка изображений с высоким уровнем безопасности.',
'app_secure_images_toggle' => 'Включить загрузку изображений с высоким уровнем безопасности',
'app_secure_images_desc' => 'Для высокой производительности все изображения являются общедоступными. Этот параметр добавляет случайную строку перед URL изображения. Убедитесь, что индексация каталогов отключена, для предотвращения легкого доступа.',
'app_editor' => 'Редактор страницы',
'app_editor_desc' => 'Выберите, какой редактор будет использоваться всеми пользователями для редактирования страниц.',
'app_custom_html' => 'Пользовательский контент заголовка HTML',
'app_custom_html_desc' => 'Любой контент, добавленный здесь, будет вставлен в нижнюю часть раздела <head> каждой страницы. Это удобно для переопределения стилей или добавления кода аналитики.',
'app_logo' => 'Лого приложения',
'app_logo_desc' => 'Это изображение должно быть 43px в высоту. <br>Большое изображение будет уменьшено.',
'app_primary_color' => 'Главный цвет приложения',
'app_primary_color' => 'Основной цвет приложения',
'app_primary_color_desc' => 'Значение должно быть указано в hex-формате. <br>Оставьте пустым чтобы использовать цвет по умолчанию.',
'app_homepage' => 'Домашняя страница приложения',
'app_homepage' => 'Стартовая страница приложения',
'app_homepage_desc' => 'Выберите страницу, которая будет отображаться на главной странице вместо стандартной. Права на страницы игнорируются для выбранных страниц.',
'app_homepage_default' => 'Выбрана домашняя страница по умолчанию',
'app_homepage_books' => 'Или выберите страницу со списком книг в качестве главной страницы. Это будет иметь приоритет над любой другой страницей.',
'app_disable_comments' => 'Отключить комментарии',
'app_disable_comments_desc' => 'Отключить комментарии на всех страницах приложения. Существующие комментарии не отображаются.',
/**
* Registration settings
*/
'app_homepage_select' => 'Выберите страницу',
'app_disable_comments' => 'Отключение комментов',
'app_disable_comments_toggle' => 'Отключить комментарии',
'app_disable_comments_desc' => 'Отключение комментов на всех страницах. Существующие комментарии отображаться не будут.',
// Registration Settings
'reg_settings' => 'Настройки регистрации',
'reg_allow' => 'Открыть регистрацию?',
'reg_enable' => 'Разрешить регистрацияю',
'reg_enable_toggle' => 'Разрешить регистрацию',
'reg_enable_desc' => 'Если регистрация разрешена, пользователь сможет зарегистрироваться в системе самомтоятельно. При регистрации назначается роль пользователя по умолчанию',
'reg_default_role' => 'Роль пользователя по умолчанию после регистрации',
'reg_confirm_email' => 'Требуется подтверждение по электронной почте?',
'reg_email_confirmation' => 'Подтверждение электонной почты',
'reg_email_confirmation_toggle' => 'Требовать подтверждение по электронной почте',
'reg_confirm_email_desc' => 'Если используется ограничение по домену, подтверждение будет обязательно, а этот пункт проигнорирован.',
'reg_confirm_restrict_domain' => 'Ограничить регистрацию по домену',
'reg_confirm_restrict_domain_desc' => 'Введите список доменов почты через запятую, для которых возможна регистрация. Пользователям будет отправлено письмо для подтверждения адреса перед входом в приложение. <br> Обратите внимание, что пользователи смогут изменить свои адреса уже после регистрации.',
'reg_confirm_restrict_domain_placeholder' => 'Нет ограничений',
/**
* Maintenance settings
*/
'reg_confirm_restrict_domain_desc' => 'Введите список доменов почты через запятую, для которых разрешена регистрация. Пользователям будет отправлено письмо для подтверждения адреса перед входом в приложение. <br> Обратите внимание, что пользователи смогут изменить свои адреса уже после регистрации.',
'reg_confirm_restrict_domain_placeholder' => 'Без ограничений',
// Maintenance settings
'maint' => 'Обслуживание',
'maint_image_cleanup' => 'Очистка изображений',
'maint_image_cleanup_desc' => 'Сканирует содержимое страниц и предыдущих версий и определяет изображения, которые не используются. Убедитесь, что у вас есть резервная копия базы данных и папки изображений перед запуском этой функции.',
'maint_image_cleanup_ignore_revisions' => 'Пропускать изображения в версиях',
'maint_image_cleanup_run' => 'Запустить очистку',
'maint_image_cleanup_run' => 'Выполнить очистку',
'maint_image_cleanup_warning' => 'Найдено :count возможно бесполезных изображений. Вы уверены, что хотите удалить эти изображения?',
'maint_image_cleanup_success' => ':count возможно бесполезных изображений было найдено и удалено!',
'maint_image_cleanup_nothing_found' => 'Не найдено ни одного бесполезного изображения!',
/**
* Role settings
*/
// Role Settings
'roles' => 'Роли',
'role_user_roles' => 'Роли пользователя',
'role_create' => 'Создать новую роль',
'role_create_success' => 'Роль упешно создана',
'role_create' => 'Добавить роль',
'role_create_success' => 'Роль упешно добавлена',
'role_delete' => 'Удалить роль',
'role_delete_confirm' => 'Это удалит роль с именем \':roleName\'.',
'role_delete_users_assigned' => 'Эта роль назначена :userCount пользователям. Если вы хотите перенести их из этой роли, выберите новую роль ниже.',
@@ -81,7 +77,7 @@ return [
'role_edit' => 'Редактировать роль',
'role_details' => 'Детали роли',
'role_name' => 'Имя роли',
'role_desc' => 'Короткое описание роли',
'role_desc' => 'Краткое описание роли',
'role_external_auth_id' => 'Внешние ID авторизации',
'role_system' => 'Системные разрешения',
'role_manage_users' => 'Управление пользователями',
@@ -91,37 +87,43 @@ return [
'role_manage_settings' => 'Управление настройками приложения',
'role_asset' => 'Разрешение для активации',
'role_asset_desc' => 'Эти разрешения контролируют доступ по умолчанию к параметрам внутри системы. Разрешения на книги, главы и страницы перезапишут эти разрешения.',
'role_asset_admins' => 'Администраторы автоматически получают доступ ко всему контенту, но эти опции могут отображать или скрывать параметры пользовательского интерфейса.',
'role_all' => 'Все',
'role_own' => 'Владелец',
'role_controlled_by_asset' => 'Регулируемые активацией они загружаются в',
'role_controlled_by_asset' => 'Контролируется активом, в который они загружены',
'role_save' => 'Сохранить роль',
'role_update_success' => 'Роль успешно обновлена',
'role_users' => 'Пользователи с данной ролью',
'role_users_none' => 'Нет пользователей с данной ролью',
/**
* Users
*/
// Users
'users' => 'Пользователи',
'user_profile' => 'Профиль пользователя',
'users_add_new' => 'Добавить нового пользователя',
'users_add_new' => 'Добавить пользователя',
'users_search' => 'Поиск пользователей',
'users_details' => 'Данные пользователя',
'users_details_desc' => 'Задайте имя для этого пользователя, чтобы другие могли его узнать',
'users_details_desc_no_email' => 'Задайте имя для этого пользователя, чтобы другие могли его узнать',
'users_role' => 'Роли пользователя',
'users_role_desc' => 'Назначьте роли пользователю. Если назначено несколько ролей, разрешения будут суммироваться и пользователь получит все права назначенных ролей.',
'users_password' => 'Пароль пользователя',
'users_password_desc' => 'Установите пароль для входа в приложение. Должно быть не менее 5 символов.',
'users_external_auth_id' => 'Внешний ID аутентификации',
'users_password_warning' => 'Введите ниже свой пароль новый пароль для его изменения:',
'users_external_auth_id_desc' => 'Этот ID используется для связи с вашей LDAP системой.',
'users_password_warning' => 'Заполните ниже только если вы хотите сменить свой пароль.',
'users_system_public' => 'Этот пользователь представляет любых гостевых пользователей, которые посещают ваше приложение. Он не может использоваться для входа в систему и назначается автоматически.',
'users_delete' => 'Удалить пользователя',
'users_delete_named' => 'Удалить пользователя :userName',
'users_delete_warning' => 'Это полностью удалит этого пользователя с именем \':userName\' из системы.',
'users_delete_warning' => 'Это полностью удалит пользователя с именем \':userName\' из системы.',
'users_delete_confirm' => 'Вы уверены что хотите удалить этого пользователя?',
'users_delete_success' => 'Пользователи успешно удалены',
'users_edit' => 'Редактировать польщователя',
'users_edit' => 'Редактировать пользователя',
'users_edit_profile' => 'Редактировать профиль',
'users_edit_success' => 'Пользователь успешно обновлен',
'users_avatar' => 'Аватар пользователя',
'users_avatar_desc' => 'Это изображение должно быть размером около 256px.',
'users_avatar_desc' => 'Выберите изображение. Изображение должно быть квадратным, размером около 256px.',
'users_preferred_language' => 'Предпочитаемый язык',
'users_preferred_language_desc' => 'Этот параметр изменит язык интерфейса приложения. Это не влияет на созданный пользователем контент.',
'users_social_accounts' => 'Аккаунты Соцсетей',
'users_social_accounts_info' => 'Здесь вы можете подключить другие учетные записи для более быстрого и легкого входа в систему. Отключение учетной записи здесь не разрешено. Отменить доступ к настройкам вашего профиля в подключенном социальном аккаунте.',
'users_social_connect' => 'Подключить аккаунт',

View File

@@ -32,6 +32,8 @@ return [
'remember_me' => 'Kom ihåg mig',
'ldap_email_hint' => 'Vänligen ange en e-postadress att använda till kontot.',
'create_account' => 'Skapa konto',
'already_have_account' => 'Har du redan en användare?',
'dont_have_account' => 'Har du ingen användare?',
'social_login' => 'Logga in genom socialt medie',
'social_registration' => 'Registrera dig genom socialt media',
'social_registration_text' => 'Registrera dig och logga in genom en annan tjänst.',
@@ -73,4 +75,4 @@ return [
'email_not_confirmed_click_link' => 'Vänligen klicka på länken i det mail du fick strax efter att du registerade dig.',
'email_not_confirmed_resend' => 'Om du inte hittar mailet kan du begära en ny bekräftelse genom att fylla i formuläret nedan.',
'email_not_confirmed_resend_button' => 'Skicka bekräftelse på nytt',
];
];

View File

@@ -10,6 +10,7 @@ return [
'save' => 'Spara',
'continue' => 'Fortsätt',
'select' => 'Välj',
'toggle_all' => 'Ändra alla',
'more' => 'Mer',
/**
@@ -26,6 +27,7 @@ return [
*/
'actions' => 'Åtgärder',
'view' => 'Visa',
'view_all' => 'Visa alla',
'create' => 'Skapa',
'update' => 'Uppdatera',
'edit' => 'Redigera',
@@ -40,6 +42,13 @@ return [
'remove' => 'Radera',
'add' => 'Lägg till',
/**
* Sort Options
*/
'sort_name' => 'Namn',
'sort_created_at' => 'Skapad',
'sort_updated_at' => 'Uppdaterad',
/**
* Misc
*/
@@ -60,6 +69,12 @@ return [
'view_profile' => 'Visa profil',
'edit_profile' => 'Redigera profil',
/**
* Layout tabs
*/
'tab_info' => 'Information',
'tab_content' => 'Innehåll',
/**
* Email Content
*/

View File

@@ -9,6 +9,7 @@ return [
'recently_updated_pages' => 'Sidor som uppdaterats nyligen',
'recently_created_chapters' => 'Kapitel som skapats nyligen',
'recently_created_books' => 'Böcker som skapats nyligen',
'recently_created_shelves' => 'Hyllor som skapats nyligen',
'recently_update' => 'Nyligen uppdaterat',
'recently_viewed' => 'Nyligen läst',
'recent_activity' => 'Aktivitet',
@@ -76,6 +77,7 @@ return [
'books_popular' => 'Populära böcker',
'books_recent' => 'Nya böcker',
'books_new' => 'Nya böcker',
'books_new_action' => 'Ny bok',
'books_popular_empty' => 'De mest populära böckerna kommer att visas här.',
'books_new_empty' => 'De senaste böckerna som skapats kommer att visas här.',
'books_create' => 'Skapa ny bok',
@@ -91,7 +93,6 @@ return [
'books_permissions_updated' => 'Bokens rättigheter har uppdaterats',
'books_empty_contents' => 'Det finns inga sidor eller kapitel i den här boken.',
'books_empty_create_page' => 'Skapa en ny sida',
'books_empty_or' => 'eller',
'books_empty_sort_current_book' => 'Sortera aktuell bok',
'books_empty_add_chapter' => 'Lägg till kapitel',
'books_permissions_active' => 'Anpassade rättigheter är i bruk',
@@ -99,6 +100,11 @@ return [
'books_navigation' => 'Navigering',
'books_sort' => 'Sortera bokens innehåll',
'books_sort_named' => 'Sortera boken :bookName',
'books_sort_name' => 'Sortera utifrån namn',
'books_sort_created' => 'Sortera utifrån skapelse',
'books_sort_updated' => 'Sortera utifrån uppdatering',
'books_sort_chapters_first' => 'Kapitel först',
'books_sort_chapters_last' => 'Kapitel sist',
'books_sort_show_other' => 'Visa andra böcker',
'books_sort_save' => 'Spara ordning',
@@ -180,6 +186,8 @@ return [
'pages_revisions_created_by' => 'Skapad av',
'pages_revisions_date' => 'Revisionsdatum',
'pages_revisions_number' => '#',
'pages_revisions_numbered' => 'Revision #:id',
'pages_revisions_numbered_changes' => 'Revision #:id ändringar',
'pages_revisions_changelog' => 'Ändringslogg',
'pages_revisions_changes' => 'Ändringar',
'pages_revisions_current' => 'Nuvarande version',
@@ -208,11 +216,13 @@ return [
*/
'shelf' => 'Hylla',
'shelves' => 'Hyllor',
'x_shelves' => ':count hylla|:count hyllor',
'shelves_long' => 'Bokhyllor',
'shelves_empty' => 'Du har inte skapat någon hylla',
'shelves_create' => 'Skapa ny hylla',
'shelves_popular' => 'Populära hyllor',
'shelves_new' => 'Ny hylla',
'shelves_new' => 'Nya hyllor',
'shelves_new_action' => 'Ny hylla',
'shelves_popular_empty' => 'De populäraste hyllorna kommer hamna här',
'shelves_new_empty' => 'De senast skapade hyllorna kommer hamna här',
'shelves_save' => 'Spara hylla',
@@ -281,6 +291,7 @@ return [
'profile_not_created_pages' => ':userName har inte skapat några sidor',
'profile_not_created_chapters' => ':userName har inte skapat några kapitel',
'profile_not_created_books' => ':userName har inte skapat några böcker',
'profile_not_created_shelves' => ':userName har inte skapat några hyllor',
/**
* Comments
@@ -307,5 +318,6 @@ return [
*/
'revision_delete_confirm' => 'Är du säker på att du vill radera den här versionen?',
'revision_delete_success' => 'Revisionen raderad',
'revision_cannot_delete_latest' => 'Det går inte att ta bort den senaste versionen.'
'revision_cannot_delete_latest' => 'Det går inte att ta bort den senaste versionen.',
'revision_restore_confirm' => 'Är du säker på att du vill använda denna revision? Det nuvarande innehållet kommer att ersättas.'
];

View File

@@ -7,7 +7,6 @@ return [
* Contains all text strings used in the general settings sections of BookStack
* including users and roles.
*/
'settings' => 'Inställningar',
'settings_save' => 'Spara inställningar',
'settings_save_success' => 'Inställningarna har sparats',
@@ -15,13 +14,18 @@ return [
/**
* App settings
*/
'app_settings' => 'Appinställningar',
'app_customization' => 'Sidanpassning',
'app_features_security' => 'Funktioner och säkerhet',
'app_name' => 'Applikationsnamn',
'app_name_desc' => 'Namnet visas i sidhuvdet och i eventuella mail.',
'app_name_header' => 'Visa applikationsnamn i sidhuvudet?',
'app_public_access' => 'Offentlig åtkomst',
'app_public_access_desc' => 'Om du aktiverar detta alternativ låter du icke inloggade besökare komma åt innehåll på din sida',
'app_public_access_desc_guest' => 'Åtkomst för icke inloggade besökare kan styras via användaren "Guest".',
'app_public_access_toggle' => 'Tillåt offentlig åtkomst',
'app_public_viewing' => 'Tillåt publikt innehåll?',
'app_secure_images' => 'Aktivera högre säkerhet för bilduppladdningar?',
'app_secure_images_toggle' => 'Aktivera säkrare bilduppladdningar',
'app_secure_images_desc' => 'Av prestandaskäl är alla bilder publika. Det här alternativet lägger till en slumpmässig, svårgissad sträng framför alla bild-URL:er. Se till att kataloglistning inte är aktivt för att förhindra åtkomst.',
'app_editor' => 'Redigeringsverktyg',
'app_editor_desc' => 'Välj vilket redigeringsverktyg som ska användas av alla användare för att redigera sidor.',
@@ -35,16 +39,19 @@ return [
'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_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.',
/**
* Registration settings
*/
'reg_settings' => 'Registreringsinställningar',
'reg_allow' => 'Tillåt registrering?',
'reg_enable' => 'Tillåt registrering',
'reg_enable_toggle' => 'Tillåt registrering',
'reg_enable_desc' => 'När registrering tillåts kan användaren logga in som en användare. Vid registreringen ges de en förvald användarroll.',
'reg_default_role' => 'Standardroll efter registrering',
'reg_confirm_email' => 'Kräv e-postbekräftelse?',
'reg_email_confirmation' => 'E-postbekräftelse',
'reg_email_confirmation_toggle' => 'Kräv e-postbekräftelse',
'reg_confirm_email_desc' => 'Om registrering begränas till vissa domäner kommer e-postbekräftelse alltid att krävas och den här inställningen kommer att ignoreras.',
'reg_confirm_restrict_domain' => 'Begränsa registrering till viss domän',
'reg_confirm_restrict_domain_desc' => 'Ange en kommaseparerad lista över e-postdomäner till vilka du vill begränsa registrering. Användare kommer att skickas ett mail för att bekräfta deras e-post innan de får logga in. <br> Notera att användare kommer att kunna ändra sin e-postadress efter lyckad registrering.',
@@ -53,7 +60,6 @@ return [
/**
* Maintenance settings
*/
'maint' => 'Underhåll',
'maint_image_cleanup' => 'Rensa bilder',
'maint_image_cleanup_desc' => "Söker igenom innehåll i sidor & revisioner för att se vilka bilder och teckningar som är i bruk och vilka som är överflödiga. Se till att ta en komplett backup av databas och bilder innan du kör detta.",
@@ -66,7 +72,6 @@ return [
/**
* Role settings
*/
'roles' => 'Roller',
'role_user_roles' => 'Användarroller',
'role_create' => 'Skapa ny roll',
@@ -102,13 +107,19 @@ return [
/**
* Users
*/
'users' => 'Användare',
'user_profile' => 'Användarprofil',
'users_add_new' => 'Lägg till användare',
'users_search' => 'Sök användare',
'users_details' => 'Användarinformation',
'users_details_desc' => 'Ange ett visningsnamn och en e-postadress för den här användaren. E-postadressen kommer att användas vid inloggningen.',
'users_details_desc_no_email' => 'Ange ett visningsnamn för den här användaren så att andra kan känna igen den.',
'users_role' => 'Användarroller',
'users_role_desc' => 'Välj vilka roller den här användaren ska tilldelas. Om en användare har tilldelats flera roller kommer behörigheterna från dessa roller att staplas och de kommer att få alla rättigheter i de tilldelade rollerna.',
'users_password' => 'Användarlösenord',
'users_password_desc' => 'Ange ett lösenord som ska användas för att logga in på sidan. Lösenordet måste vara minst 5 tecken långt.',
'users_external_auth_id' => 'Externt ID för autentisering',
'users_external_auth_id_desc' => 'Detta är det ID som används för att matcha användaren när den kommunicerar med ditt LDAP-system.',
'users_password_warning' => 'Fyll i nedanstående fält endast om du vill byta lösenord:',
'users_system_public' => 'Den här användaren representerar eventuella gäster som använder systemet. Den kan inte användas för att logga in utan tilldeles automatiskt.',
'users_delete' => 'Ta bort användare',
@@ -121,7 +132,8 @@ return [
'users_edit_success' => 'Användaren har uppdaterats',
'users_avatar' => 'Avatar',
'users_avatar_desc' => 'Bilden bör vara kvadratisk och ca 256px stor.',
'users_preferred_language' => 'Språk',
'users_preferred_language' => 'Föredraget språk',
'users_preferred_language_desc' => 'Det här alternativet kommer att ändra det språk som används i användargränssnittet. Detta påverkar inget användarskapat innehåll.',
'users_social_accounts' => 'Anslutna konton',
'users_social_accounts_info' => 'Här kan du ansluta dina andra konton för snabbare och smidigare inloggning. Om du kopplar från en tjänst här kommer de behörigheter som tidigare givits inte att tas bort - ta bort behörigheter genom att logga in på ditt konto på tjänsten i fråga.',
'users_social_connect' => 'Anslut konto',

View File

@@ -12,7 +12,6 @@ return [
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => ':attribute måste godkännas.',
'active_url' => ':attribute är inte en giltig URL.',
'after' => ':attribute måste vara efter :date.',
@@ -76,6 +75,7 @@ return [
'timezone' => ':attribute måste vara en giltig tidszon.',
'unique' => ':attribute är upptaget',
'url' => 'Formatet på :attribute är ogiltigt.',
'uploaded' => 'Filen kunde inte laddas upp. Servern kanske inte tillåter filer med denna storlek.',
/*
|--------------------------------------------------------------------------
@@ -87,7 +87,6 @@ return [
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'password-confirm' => [
'required_with' => 'Lösenordet måste bekräftas',
@@ -104,7 +103,6 @@ return [
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [],
];

View File

@@ -1,9 +1,7 @@
<?php
/**
* Activity text strings.
* Is used for all the text within activity logs & notifications.
* Текстові рядки активності.
* Використовується для всього тексту в журналах активності та сповіщеннях.
* Activity text strings. / Текстові рядки активності.
* Is used for all the text within activity logs & notifications. / Використовується для всього тексту в журналах активності та сповіщеннях.
*/
return [

View File

@@ -1,10 +1,8 @@
<?php
/**
* Authentication Language Lines
* The following language lines are used during authentication for various
* messages that we need to display to the user.
* Під час автентифікації використовуються наступні лінії мов для різних повідомлень
* які нам потрібно показати користувачеві.
* The following language lines are used during authentication for various / Під час автентифікації використовуються наступні лінії мов для різних повідомлень
* messages that we need to display to the user. / які нам потрібно показати користувачеві.
*/
return [
@@ -18,7 +16,7 @@ return [
'sign_up_with' => 'Зареєструватись з :socialDriver',
'logout' => 'Вихід',
'name' => 'Імя',
'name' => 'Ім\'я',
'username' => 'Логін',
'email' => 'Email',
'password' => 'Пароль',
@@ -28,6 +26,8 @@ return [
'remember_me' => 'Запам’ятати мене',
'ldap_email_hint' => 'Введіть email для цього облікового запису.',
'create_account' => 'Створити обліковий запис',
'already_have_account' => 'Вже є обліковий запис?',
'dont_have_account' => 'Немає облікового запису?',
'social_login' => 'Вхід через соціальну мережу',
'social_registration' => 'Реєстрація через соціальну мережу',
'social_registration_text' => 'Реєстрація і вхід через інший сервіс',
@@ -35,7 +35,7 @@ return [
'register_thanks' => 'Дякуємо за реєстрацію!',
'register_confirm' => 'Будь ласка, перевірте свою електронну пошту та натисніть кнопку підтвердження, щоб отримати доступ до :appName.',
'registrations_disabled' => 'Реєстрацію вимкнено',
'registration_email_domain_invalid' => 'Цей домен електронної пошти не має доступу до реєстрації',
'registration_email_domain_invalid' => 'Цей домен електронної пошти заборонений для реєстрації',
'register_success' => 'Дякуємо за реєстрацію! Ви зареєстровані та ввійшли в систему.',
@@ -64,4 +64,4 @@ return [
'email_not_confirmed_click_link' => 'Будь-ласка, натисніть на посилання в електронному листі, яке було надіслано після реєстрації.',
'email_not_confirmed_resend' => 'Якщо ви не можете знайти електронний лист, ви можете повторно надіслати підтвердження електронною поштою, на формі нижче.',
'email_not_confirmed_resend_button' => 'Повторне підтвердження електронної пошти',
];
];

View File

@@ -1,7 +1,6 @@
<?php
/**
* Common elements found throughout many areas of BookStack.
* Загальні елементи, використовуються в багатьох областях BookStack.
* Common elements found throughout many areas of BookStack. / Загальні елементи, використовуються в багатьох областях BookStack.
*/
return [
@@ -12,6 +11,7 @@ return [
'save' => 'Зберегти',
'continue' => 'Продовжити',
'select' => 'Вибрати',
'toggle_all' => 'Увімкнути все',
'more' => 'Ще',
// Form Labels
@@ -23,7 +23,8 @@ return [
// Actions
'actions' => 'Дії',
'view' => ерегляд',
'view' => одивитись',
'view_all' => 'Подивитись все',
'create' => 'Створити',
'update' => 'Оновити',
'edit' => 'Редагувати',
@@ -37,6 +38,11 @@ return [
'reset' => 'Скинути',
'remove' => 'Видалити',
'add' => 'Додати',
// Sort Options
'sort_name' => 'Ім\'я',
'sort_created_at' => 'Дата створення',
'sort_updated_at' => 'Дата оновлення',
// Misc
'deleted_user' => 'Видалений користувач',
@@ -53,8 +59,12 @@ return [
// Header
'view_profile' => 'Переглянути профіль',
'edit_profile' => 'Редагувати профіль',
// Layout tabs
'tab_info' => 'Інфо',
'tab_content' => 'Вміст',
// Email Content
'email_action_help' => 'Якщо у вас виникають проблеми при натисканні кнопки ":actionText", скопіюйте та вставте URL у свій веб-браузер:',
'email_rights' => 'Всі права захищені',
];
];

View File

@@ -1,7 +1,6 @@
<?php
/**
* Text used in custom JavaScript driven components.
* Текст використовується в індивідуальних компонентах, керованих JavaScript.
* Text used in custom JavaScript driven components. / Текст використовується в індивідуальних компонентах, керованих JavaScript.
*/
return [

View File

@@ -1,9 +1,7 @@
<?php
/**
* Text used for 'Entities' (Document Structure Elements) such as
* Books, Shelves, Chapters & Pages
* Текст використовується для "об'єктів" (елементів структури документів), таких як
* Книги, Полиці, Розділи та Сторінки
* Text used for 'Entities' (Document Structure Elements) such as / Текст використовується для "об'єктів" (елементів структури документів), таких як
* Books, Shelves, Chapters & Pages / Книги, Полиці, Розділи та Сторінки
*/
return [
@@ -13,6 +11,7 @@ return [
'recently_updated_pages' => 'Нещодавно оновлені сторінки',
'recently_created_chapters' => 'Нещодавно створені розділи',
'recently_created_books' => 'Нещодавно створені книги',
'recently_created_shelves' => 'Нещодавно створені полиці',
'recently_update' => 'Недавно оновлено',
'recently_viewed' => 'Недавно переглянуто',
'recent_activity' => 'Остання активність',
@@ -37,7 +36,7 @@ return [
// Permissions and restrictions
'permissions' => 'Дозволи',
'permissions_intro' => 'Після ввімкнення ці дозволи будуть мати пріоритет над усіма дозволеними ролями.',
'permissions_intro' => 'Після ввімкнення ці дозволи будуть мати вищий пріоритет ніж інші дозволи ролей.',
'permissions_enable' => 'Увімкнути спеціальні дозволи',
'permissions_save' => 'Зберегти дозволи',
@@ -69,11 +68,13 @@ return [
// Shelves
'shelf' => 'Полиця',
'shelves' => 'Полиці',
'x_shelves' => ':count Полиця|:count Полиць',
'shelves_long' => 'Книжкові полиці',
'shelves_empty' => 'Жодних полиць не було створено',
'shelves_create' => 'Створити нову полицю',
'shelves_popular' => 'Популярні полиці',
'shelves_new' => 'Нові полиці',
'shelves_new_action' => 'Нова полиця',
'shelves_popular_empty' => 'Найпопулярніші полиці з\'являться тут.',
'shelves_new_empty' => 'Тут будуть з\'являтися останні створені полиці.',
'shelves_save' => 'Зберегти полицю',
@@ -104,6 +105,7 @@ return [
'books_popular' => 'Популярні книги',
'books_recent' => 'Останні книги',
'books_new' => 'Нові книги',
'books_new_action' => 'Нова книга',
'books_popular_empty' => 'Найпопулярніші книги з\'являться тут.',
'books_new_empty' => 'Найновіші книги з\'являться тут.',
'books_create' => 'Створити нову книгу',
@@ -119,7 +121,6 @@ return [
'books_permissions_updated' => 'Дозволи на книгу оновлено',
'books_empty_contents' => 'Для цієї книги не створено жодної сторінки або розділів.',
'books_empty_create_page' => 'Створити нову сторінку',
'books_empty_or' => 'або',
'books_empty_sort_current_book' => 'Сортувати поточну книгу',
'books_empty_add_chapter' => 'Додати розділ',
'books_permissions_active' => 'Діючі дозволи на книгу',
@@ -127,6 +128,11 @@ return [
'books_navigation' => 'Навігація по книзі',
'books_sort' => 'Сортувати вміст книги',
'books_sort_named' => 'Сортувати книгу :bookName',
'books_sort_name' => 'Сортувати за назвою',
'books_sort_created' => 'Сортувати за датою створення',
'books_sort_updated' => 'Сортувати за датою оновлення',
'books_sort_chapters_first' => 'Спершу розділи',
'books_sort_chapters_last' => 'Розділи в кінці',
'books_sort_show_other' => 'Показати інші книги',
'books_sort_save' => 'Зберегти нове замовлення',
@@ -204,6 +210,8 @@ return [
'pages_revisions_created_by' => 'Створена',
'pages_revisions_date' => 'Дата версії',
'pages_revisions_number' => '#',
'pages_revisions_numbered' => 'Версія #:id',
'pages_revisions_numbered_changes' => 'Зміни версії #:id',
'pages_revisions_changelog' => 'Історія змін',
'pages_revisions_changes' => 'Зміни',
'pages_revisions_current' => 'Поточна версія',
@@ -218,7 +226,7 @@ return [
'pages_editing_draft_notification' => 'Ви наразі редагуєте чернетку, що була збережена останньою :timeDiff.',
'pages_draft_edited_notification' => 'З того часу ця сторінка була оновлена. Рекомендуємо відмовитися від цього проекту.',
'pages_draft_edit_active' => [
'start_a' => ':count користувачі(в) почала редагувати цю сторінку',
'start_a' => ':count користувачі(в) почали редагувати цю сторінку',
'start_b' => ':userName розпочав редагування цієї сторінки',
'time_a' => 'з моменту останньої оновлення сторінки',
'time_b' => 'за останні :minCount хвилин',
@@ -269,6 +277,7 @@ return [
'profile_not_created_pages' => ':userName не створив жодної сторінки',
'profile_not_created_chapters' => ':userName не створив жодного розділу',
'profile_not_created_books' => ':userName не створив жодної книги',
'profile_not_created_shelves' => ':userName не створив жодної полиці',
// Comments
'comment' => 'Коментар',
@@ -290,6 +299,7 @@ return [
// Revision
'revision_delete_confirm' => 'Ви впевнені, що хочете видалити цю версію?',
'revision_restore_confirm' => 'Дійсно відновити цю версію? Вміст поточної сторінки буде замінено.',
'revision_delete_success' => 'Версія видалена',
'revision_cannot_delete_latest' => 'Неможливо видалити останню версію.'
];
];

View File

@@ -1,7 +1,6 @@
<?php
/**
* Text shown in error messaging.
* Текст відображається в повідомленнях про помилку.
* Text shown in error messaging. / Текст відображається в повідомленнях про помилку.
*/
return [
@@ -37,6 +36,7 @@ return [
'uploaded' => 'Сервер не дозволяє завантажувати файли такого розміру. Спробуйте менший розмір файлу.',
'image_upload_error' => 'Виникла помилка під час завантаження зображення',
'image_upload_type_error' => 'Тип завантаженого зображення недійсний',
'file_upload_timeout' => 'Тайм-аут при завантаженні файлу',
// Attachments
'attachment_page_mismatch' => 'Невідповідність сторінки при оновленні вкладень',
@@ -64,6 +64,7 @@ return [
'role_cannot_be_edited' => 'Цю роль не можна редагувати',
'role_system_cannot_be_deleted' => 'Ця роль є системною, і її не можна видалити',
'role_registration_default_cannot_delete' => 'Цю роль не можна видалити, бо вона встановлена як роль реєстрації за умовчанням',
'role_cannot_remove_only_admin' => 'Цей користувач є єдиним користувачем, призначеним для ролі адміністратора. Призначте роль адміністратора іншому користувачеві, перш ніж спробувати його видалити.',
// Comments
'comment_list' => 'Під час отримання коментарів сталася помилка.',

View File

@@ -1,11 +1,8 @@
<?php
/**
* Pagination Language Lines
* The following language lines are used by the paginator library to build
* the simple pagination links.
* Лінії мови вирівнювання по сторінках
* Наступні мовні лінії використовуються бібліотекою журналіста для створення
* простих посилань на сторінки.
* Pagination Language Lines / Лінії мови вирівнювання по сторінках
* The following language lines are used by the paginator library to build / Наступні мовні лінії використовуються бібліотекою журналіста для створення
* the simple pagination links. / простих посилань на сторінки.
*/
return [

View File

@@ -1,9 +1,8 @@
<?php
/**
* Password Reminder Language Lines
* 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 [

View File

@@ -1,11 +1,8 @@
<?php
/**
* Settings text strings
* Contains all text strings used in the general settings sections of BookStack
* including users and roles.
* Текст налаштувань
* Містить всі текстові рядки, що використовуються в розділах загальної настройки BookStack
* включаючи користувачів та ролі.
* Settings text strings / Текст налаштувань
* Contains all text strings used in the general settings sections of BookStack / Містить всі текстові рядки, що використовуються в розділах загальної настройки BookStack
* including users and roles. / включаючи користувачів та ролі.
*/
return [
@@ -15,12 +12,18 @@ return [
'settings_save_success' => 'Налаштування збережено',
// App Settings
'app_settings' => 'Налаштування програми',
'app_customization' => 'Налаштування',
'app_features_security' => 'Особливості та безпека',
'app_name' => 'Назва програми',
'app_name_desc' => 'Ця назва відображається у заголовку та у всіх листах.',
'app_name_header' => 'Показати назву програми в заголовку?',
'app_name_header' => 'Показати назву програми в заголовку',
'app_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' => 'Вищі налаштування безпеки для зображень',
'app_secure_images_toggle' => 'Увімкунти вищі налаштування безпеки для завантаження зображень',
'app_secure_images_desc' => 'З міркувань продуктивності всі зображення є загальнодоступними. Цей параметр додає випадковий, важко передбачуваний рядок перед URL-адресами зображень. Переконайтеся, що індексація каталогів не активована, щоб запобігти легкому доступу.',
'app_editor' => 'Редактор сторінок',
'app_editor_desc' => 'Виберіть, який редактор буде використовуватися всіма користувачами для редагування сторінок.',
@@ -34,15 +37,19 @@ return [
'app_homepage_desc' => 'Виберіть сторінку, яка відображатиметься на домашній сторінці замість перегляду за умовчанням. Права на сторінку не враховуються для вибраних сторінок.',
'app_homepage_select' => 'Вибрати сторінку',
'app_disable_comments' => 'Вимкнути коментарі',
'app_disable_comments_toggle' => 'Вимкнути коментарі',
'app_disable_comments_desc' => 'Вимкнути коментарі на всіх сторінках програми. Існуючі коментарі не відображаються.',
// Registration Settings
'reg_settings' => 'Налаштування реєстрації',
'reg_allow' => 'Дозволити реєстрацію?',
'reg_settings' => 'Реєстрація',
'reg_enable' => 'Дозволити реєстрацію',
'reg_enable_toggle' => 'Дозволити реєстрацію',
'reg_enable_desc' => 'При включенні реєстрації відвідувач зможе зареєструватися як користувач програми. Після реєстрації їм надається єдина роль користувача за замовчуванням.',
'reg_default_role' => 'Роль користувача за умовчанням після реєстрації',
'reg_confirm_email' => отрібне підтвердження електронною поштою?',
'reg_email_confirmation' => 'Підтвердження електронною поштою',
'reg_email_confirmation_toggle' => 'Необхідне підтвердження електронною поштою',
'reg_confirm_email_desc' => 'Якщо використовується обмеження домену, то підтвердження електронною поштою буде потрібно, а нижче значення буде проігноровано.',
'reg_confirm_restrict_domain' => 'Обмежити реєстрацію до домену',
'reg_confirm_restrict_domain' => 'Обмежити по домену',
'reg_confirm_restrict_domain_desc' => 'Введіть список розділених комами доменів електронної пошти, до яких ви хочете обмежити реєстрацію. Користувачам буде надіслано електронне повідомлення для підтвердження своєї адреси, перш ніж дозволяти взаємодіяти з додатком. <br> Зауважте, що користувачі зможуть змінювати свої електронні адреси після успішної реєстрації.',
'reg_confirm_restrict_domain_placeholder' => 'Не встановлено обмежень',
@@ -94,8 +101,15 @@ return [
'user_profile' => 'Профіль користувача',
'users_add_new' => 'Додати нового користувача',
'users_search' => 'Пошук користувачів',
'users_details' => 'Відомості про користувача',
'users_details_desc' => 'Встановіть ім\'я та електронну адресу для цього користувача. Адреса електронної пошти буде використана для входу до програми.',
'users_details_desc_no_email' => 'Встановіть ім\'я для цього користувача, щоб інші могли його розпізнати.',
'users_role' => 'Ролі користувача',
'users_role_desc' => 'Виберіть, до яких ролей буде призначено цього користувача. Якщо користувачеві призначено декілька ролей, дозволи з цих ролей будуть складатись і вони отримуватимуть усі можливості призначених ролей.',
'users_password' => 'Пароль користувача',
'users_password_desc' => 'Встановіть пароль для входу. Він повинен містити принаймні 5 символів.',
'users_external_auth_id' => 'Зовнішній ID автентифікації',
'users_external_auth_id_desc' => 'Цей ID використовується для пошуку збігу цього користувача під час зв\'язку з LDAP.',
'users_password_warning' => 'Тільки якщо ви хочете змінити свій пароль, заповніть поля нижче:',
'users_system_public' => 'Цей користувач представляє будь-яких гостьових користувачів, які відвідують ваш екземпляр. Його не можна використовувати для входу, але він призначається автоматично.',
'users_delete' => 'Видалити користувача',
@@ -109,6 +123,7 @@ return [
'users_avatar' => 'Аватар користувача',
'users_avatar_desc' => 'Це квадратне зображення має бути приблизно 256px.',
'users_preferred_language' => 'Бажана мова',
'users_preferred_language_desc' => 'Цей параметр змінить мову інтерфейсу користувача в програмі. Не вплине на створений користувачем вміст.',
'users_social_accounts' => 'Соціальні акаунти',
'users_social_accounts_info' => 'Тут ви можете підключити інші облікові записи для швидшого та легшого входу. Від\'єднання соціального облікового запису тут не дозволяється. Скасуйте доступ із налаштувань вашого профілю в пов\'язаній соціальній мережі.',
'users_social_connect' => 'Підключити обліковий запис',

View File

@@ -1,13 +1,9 @@
<?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.
* Стрічки перевірки
* Наступні мовні лінії містять повідомлення про помилку за замовчуванням,
* що використовуються класом валідатора. Деякі з цих правил мають кілька версій,
* таких як правила розмірів. Ви можете налаштувати кожен з цих повідомлень тут.
* 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 [
@@ -37,6 +33,7 @@ return [
'filled' => ':attribute поле обов\'язкове.',
'exists' => 'Вибраний :attribute недійсний.',
'image' => ':attribute повинен бути зображенням.',
'image_extension' => ':attribute повинен мати дійсне та підтримуване розширення зображення.',
'in' => 'Вибраний :attribute недійсний.',
'integer' => ':attribute повинен бути цілим числом.',
'ip' => ':attribute повинна бути дійсною IP-адресою.',
@@ -53,6 +50,7 @@ return [
'string' => ':attribute повинен бути принаймні :min символів.',
'array' => ':attribute повинен містити принаймні :min елементів.',
],
'no_double_extension' => ':attribute повинен мати тільки одне розширення файлу.',
'not_in' => 'Вибраний :attribute недійсний.',
'numeric' => ':attribute повинен бути числом.',
'regex' => ':attribute формат недійсний.',
@@ -73,6 +71,7 @@ return [
'timezone' => ':attribute повинен бути дійсною зоною.',
'unique' => ':attribute вже є.',
'url' => ':attribute формат недійсний.',
'uploaded' => 'Не вдалося завантажити файл. Сервер може не приймати файли такого розміру.',
// Custom validation lines
'custom' => [

View File

@@ -15,5 +15,5 @@
<div class="form-group">
<label for="password">{{ trans('auth.password') }}</label>
@include('form.password', ['name' => 'password', 'tabindex' => 2])
@include('form.password', ['name' => 'password', 'tabindex' => 1])
</div>

View File

@@ -27,7 +27,7 @@
</div>
<div class="text-right">
<button class="button primary" tabindex="3">{{ title_case(trans('auth.log_in')) }}</button>
<button class="button primary" tabindex="1">{{ title_case(trans('auth.log_in')) }}</button>
</div>
</div>
@@ -46,7 +46,7 @@
@endif
@if(setting('registration-enabled', false))
<div class="text-center">
<div class="text-center pb-s">
<hr class="my-l">
<a href="{{ baseUrl('/register') }}">{{ trans('auth.dont_have_account') }}</a>
</div>

View File

@@ -58,7 +58,7 @@
<h1 id="{{$bookChild->getType()}}-{{$bookChild->id}}">{{ $bookChild->name }}</h1>
@if($bookChild->isA('chapter'))
<p>{{ $bookChild->description }}</p>
<p>{{ $bookChild->text }}</p>
@if(count($bookChild->pages) > 0)
@foreach($bookChild->pages as $page)

View File

@@ -1,7 +1,5 @@
@extends('tri-layout')
@section('container-classes', 'mt-xl')
@section('body')
@include('books.list', ['books' => $books, 'view' => $view])
@stop

View File

@@ -1,8 +1,8 @@
<div class="content-wrap mt-m card">
<div class="grid half v-center">
<div class="grid half v-center no-row-gap">
<h1 class="list-heading">{{ trans('entities.books') }}</h1>
<div class="text-right">
<div class="text-m-right my-m">
@include('partials.sort', ['options' => $sortOptions, 'order' => $order, 'sort' => $sort, 'type' => 'books'])

View File

@@ -1,8 +1,8 @@
<div page-comments page-id="{{ $page->id }}" class="comments-list">
<div comment-count-bar class="grid half left-focus v-center">
<div comment-count-bar class="grid half left-focus v-center no-row-gap">
<h5 comments-title>{{ trans_choice('entities.comment_count', count($page->comments), ['count' => count($page->comments)]) }}</h5>
@if (count($page->comments) === 0)
<div class="text-right" comment-add-button-container>
<div class="text-m-right" comment-add-button-container>
<button type="button" action="addComment"
class="button outline">{{ trans('entities.comment_add') }}</button>
</div>

View File

@@ -1,23 +1,19 @@
@extends('simple-layout')
@extends('tri-layout')
@section('body')
<div class="container mt-m">
<div class="grid right-focus gap-xl">
<div>
@include('books.list', ['books' => $books, 'view' => $view])
@stop
<div class="actions mb-xl">
<h5>{{ trans('common.actions') }}</h5>
<div class="icon-list text-primary">
@include('partials.view-toggle', ['view' => $view, 'type' => 'book'])
@include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
</div>
</div>
@section('left')
@include('common.home-sidebar')
@stop
@include('common.home-sidebar')
</div>
<div>
@include('books.list', ['books' => $books, 'view' => $view])
</div>
@section('right')
<div class="actions mb-xl">
<h5>{{ trans('common.actions') }}</h5>
<div class="icon-list text-primary">
@include('partials.view-toggle', ['view' => $view, 'type' => 'book'])
@include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
</div>
</div>
@stop

View File

@@ -1,26 +1,24 @@
@extends('simple-layout')
@extends('tri-layout')
@section('body')
<div class="container mt-l">
<div class="grid right-focus gap-xl">
<div>
<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'])
</div>
</div>
@include('common.home-sidebar')
</div>
<div>
<div class="content-wrap card">
<div class="page-content" page-display="{{ $customHomepage->id }}">
@include('pages.page-display', ['page' => $customHomepage])
</div>
</div>
<div class="mt-m">
<div class="content-wrap card">
<div class="page-content" page-display="{{ $customHomepage->id }}">
@include('pages.page-display', ['page' => $customHomepage])
</div>
</div>
</div>
@stop
@section('left')
@include('common.home-sidebar')
@stop
@section('right')
<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'])
</div>
</div>
@stop

View File

@@ -1,23 +1,19 @@
@extends('simple-layout')
@extends('tri-layout')
@section('body')
<div class="container mt-m">
<div class="grid right-focus gap-xl">
<div>
@include('shelves.list', ['shelves' => $shelves, 'view' => $view])
@stop
<div class="actions mb-xl">
<h5>{{ trans('common.actions') }}</h5>
<div class="icon-list text-primary">
@include('partials.view-toggle', ['view' => $view, 'type' => 'shelf'])
@include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
</div>
</div>
@section('left')
@include('common.home-sidebar')
@stop
@include('common.home-sidebar')
</div>
<div>
@include('shelves.list', ['shelves' => $shelves, 'view' => $view])
</div>
@section('right')
<div class="actions mb-xl">
<h5>{{ trans('common.actions') }}</h5>
<div class="icon-list text-primary">
@include('partials.view-toggle', ['view' => $view, 'type' => 'shelf'])
@include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
</div>
</div>
@stop

View File

@@ -20,7 +20,7 @@
<div class="grid third gap-xxl">
<div>
<div class="card mb-xl">
<h3>{{ trans('entities.pages_popular') }}</h3>
<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'])
</div>
@@ -28,7 +28,7 @@
</div>
<div>
<div class="card mb-xl">
<h3>{{ trans('entities.books_popular') }}</h3>
<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'])
</div>
@@ -36,7 +36,7 @@
</div>
<div>
<div class="card mb-xl">
<h3>{{ trans('entities.chapters_popular') }}</h3>
<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'])
</div>

View File

@@ -12,7 +12,7 @@
{{--Header Bar--}}
<div class="primary-background-light toolbar page-edit-toolbar">
<div class="grid third v-center">
<div class="grid third no-break v-center">
<div class="action-buttons text-left px-m py-xs">
<a href="{{ back()->getTargetUrl() }}" class="text-button text-primary">@icon('back')<span class="hide-under-l">{{ trans('common.back') }}</span></a>
@@ -49,7 +49,7 @@
<span>{{-- Prevents button jumping on menu show --}}</span>
</div>
<button type="submit" id="save-button" class="float-left text-primary text-button text-pos-hover">@icon('save')<span>{{ trans('entities.pages_save') }}</span></button>
<button type="submit" id="save-button" class="float-left text-primary text-button text-pos-hover hide-under-m">@icon('save')<span>{{ trans('entities.pages_save') }}</span></button>
</div>
</div>
</div>
@@ -120,4 +120,6 @@
@endif
</div>
<button type="submit" id="save-button-mobile" title="{{ trans('entities.pages_save') }}" class="text-primary text-button hide-over-m page-save-mobile-button">@icon('save')</button>
</div>

View File

@@ -190,6 +190,11 @@
<div>
<div v-pre class="card content-wrap">
<h1 class="list-heading">{{ trans('entities.search_results') }}</h1>
<form action="{{ baseUrl('/search') }}" method="GET" class="search-box flexible hide-over-l">
<input value="{{$searchTerm}}" type="text" name="term" placeholder="{{ trans('common.search') }}">
<button type="submit">@icon('search')</button>
<button v-if="searching" v-cloak class="search-box-cancel text-neg" v-on:click="clearSearch" type="button">@icon('close')</button>
</form>
<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])

View File

@@ -1,5 +1,6 @@
<?php namespace Tests;
use BookStack\Entities\Page;
use BookStack\Notifications\ConfirmEmail;
use BookStack\Auth\User;
use BookStack\Settings\SettingService;
@@ -334,6 +335,17 @@ class AuthTest extends BrowserKitTest
->seeLink('Sign up');
}
public function test_login_redirects_to_initially_requested_url_correctly()
{
config()->set('app.url', 'http://localhost');
$page = Page::query()->first();
$this->visit($page->getUrl())
->seePageUrlIs(baseUrl('/login'));
$this->login('admin@admin.com', 'password')
->seePageUrlIs($page->getUrl());
}
/**
* Perform a login
* @param string $email

View File

@@ -76,6 +76,20 @@ class ExportTest extends TestCase
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.html"');
}
public function test_book_html_export_shows_chapter_descriptions()
{
$chapterDesc = 'My custom test chapter description ' . str_random(12);
$chapter = Chapter::query()->first();
$chapter->description = $chapterDesc;
$chapter->save();
$book = $chapter->book;
$this->asEditor();
$resp = $this->get($book->getUrl('/export/html'));
$resp->assertSee($chapterDesc);
}
public function test_chapter_text_export()
{
$chapter = Chapter::first();

View File

@@ -84,6 +84,31 @@ class PageContentTest extends TestCase
$pageView->assertSee('abc123abc123');
}
public function test_more_complex_content_script_escaping_scenarios()
{
$checks = [
"<p>Some script</p><script>alert('cat')</script>",
"<div><div><div><div><p>Some script</p><script>alert('cat')</script></div></div></div></div>",
"<p>Some script<script>alert('cat')</script></p>",
"<p>Some script <div><script>alert('cat')</script></div></p>",
"<p>Some script <script><div>alert('cat')</script></div></p>",
"<p>Some script <script><div>alert('cat')</script><script><div>alert('cat')</script></p><script><div>alert('cat')</script>",
];
$this->asEditor();
$page = Page::first();
foreach ($checks as $check) {
$page->html = $check;
$page->save();
$pageView = $this->get($page->getUrl());
$pageView->assertElementNotContains('.page-content', '<script>');
$pageView->assertElementNotContains('.page-content', '</script>');
}
}
public function test_page_inline_on_attributes_removed_by_default()
{
$this->asEditor();
@@ -97,6 +122,29 @@ class PageContentTest extends TestCase
$pageView->assertSee('<p>Hello</p>');
}
public function test_more_complex_inline_on_attributes_escaping_scenarios()
{
$checks = [
'<p onclick="console.log(\'test\')">Hello</p>',
'<div>Lorem ipsum dolor sit amet.</div><p onclick="console.log(\'test\')">Hello</p>',
'<div>Lorem ipsum dolor sit amet.<p onclick="console.log(\'test\')">Hello</p></div>',
'<div><div><div><div>Lorem ipsum dolor sit amet.<p onclick="console.log(\'test\')">Hello</p></div></div></div></div>',
'<div onclick="console.log(\'test\')">Lorem ipsum dolor sit amet.</div><p onclick="console.log(\'test\')">Hello</p><div></div>',
];
$this->asEditor();
$page = Page::first();
foreach ($checks as $check) {
$page->html = $check;
$page->save();
$pageView = $this->get($page->getUrl());
$pageView->assertElementNotContains('.page-content', 'onclick');
}
}
public function test_page_content_scripts_show_when_configured()
{
$this->asEditor();

View File

@@ -1,19 +0,0 @@
<?php namespace Tests;
class HelpersTest extends TestCase
{
public function test_base_url_takes_config_into_account()
{
config()->set('app.url', 'http://example.com/bookstack');
$result = baseUrl('/');
$this->assertEquals('http://example.com/bookstack/', $result);
}
public function test_base_url_takes_extra_path_into_account_on_forced_domain()
{
config()->set('app.url', 'http://example.com/bookstack');
$result = baseUrl('http://example.com/bookstack/', true);
$this->assertEquals('http://example.com/bookstack/', $result);
}
}

View File

@@ -1,5 +1,7 @@
<?php namespace Tests;
use BookStack\Entities\Bookshelf;
class HomepageTest extends TestCase
{
@@ -36,10 +38,14 @@ class HomepageTest extends TestCase
$name = 'My custom homepage';
$content = str_repeat('This is the body content of my custom homepage.', 20);
$customPage = $this->newPage(['name' => $name, 'html' => $content]);
$this->setSettings(['app-homepage' => $customPage->id]);
$this->setSettings([
'app-homepage' => $customPage->id,
'app-homepage-type' => 'page'
]);
$homeVisit = $this->get('/');
$homeVisit->assertSee($name);
$homeVisit->assertElementNotExists('#home-default');
$pageDeleteReq = $this->delete($customPage->getUrl());
$pageDeleteReq->assertStatus(302);
@@ -52,6 +58,23 @@ class HomepageTest extends TestCase
$homeVisit->assertStatus(200);
}
public function test_custom_homepage_can_be_deleted_once_custom_homepage_no_longer_used()
{
$this->asEditor();
$name = 'My custom homepage';
$content = str_repeat('This is the body content of my custom homepage.', 20);
$customPage = $this->newPage(['name' => $name, 'html' => $content]);
$this->setSettings([
'app-homepage' => $customPage->id,
'app-homepage-type' => 'default'
]);
$pageDeleteReq = $this->delete($customPage->getUrl());
$pageDeleteReq->assertStatus(302);
$pageDeleteReq->assertSessionHas('success');
$pageDeleteReq->assertSessionMissing('error');
}
public function test_set_book_homepage()
{
$editor = $this->getEditor();
@@ -89,4 +112,33 @@ class HomepageTest extends TestCase
$this->setSettings(['app-homepage-type' => false]);
$this->test_default_homepage_visible();
}
public function test_shelves_list_homepage_adheres_to_book_visibility_permissions()
{
$editor = $this->getEditor();
setting()->putUser($editor, 'bookshelves_view_type', 'list');
$this->setSettings(['app-homepage-type' => 'bookshelves']);
$this->asEditor();
$shelf = Bookshelf::query()->first();
$book = $shelf->books()->first();
// Ensure initially visible
$homeVisit = $this->get('/');
$homeVisit->assertElementContains('.content-wrap', $shelf->name);
$homeVisit->assertElementContains('.content-wrap', $book->name);
// Ensure book no longer visible without view permission
$editor->roles()->detach();
$this->giveUserPermissions($editor, ['bookshelf-view-all']);
$homeVisit = $this->get('/');
$homeVisit->assertElementContains('.content-wrap', $shelf->name);
$homeVisit->assertElementNotContains('.content-wrap', $book->name);
// Ensure is visible again with entity-level view permission
$this->setEntityRestrictions($book, ['view'], [$editor->roles()->first()]);
$homeVisit = $this->get('/');
$homeVisit->assertElementContains('.content-wrap', $shelf->name);
$homeVisit->assertElementContains('.content-wrap', $book->name);
}
}

View File

@@ -0,0 +1,33 @@
<?php namespace Tests;
class HelpersTest extends TestCase
{
public function test_base_url_takes_config_into_account()
{
config()->set('app.url', 'http://example.com/bookstack');
$result = baseUrl('/');
$this->assertEquals('http://example.com/bookstack/', $result);
}
public function test_base_url_takes_extra_path_into_account_on_forced_domain()
{
config()->set('app.url', 'http://example.com/bookstack');
$result = baseUrl('http://example.com/bookstack/', true);
$this->assertEquals('http://example.com/bookstack/', $result);
}
public function test_base_url_force_domain_works_as_expected_with_full_url_given()
{
config()->set('app.url', 'http://example.com');
$result = baseUrl('http://examps.com/books/test/page/cat', true);
$this->assertEquals('http://example.com/books/test/page/cat', $result);
}
public function test_base_url_force_domain_works_when_app_domain_is_same_as_given_url()
{
config()->set('app.url', 'http://example.com');
$result = baseUrl('http://example.com/books/test/page/cat', true);
$this->assertEquals('http://example.com/books/test/page/cat', $result);
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Tests;
use BookStack\Entities\Repos\PageRepo;
class PageRepoTest extends TestCase
{
/**
* @var PageRepo $pageRepo
*/
protected $pageRepo;
protected function setUp()
{
parent::setUp();
$this->pageRepo = app()->make(PageRepo::class);
}
public function test_get_page_nav_does_not_show_empty_titles()
{
$content = '<h1 id="testa">Hello</h1><h2 id="testb">&nbsp;</h2><h3 id="testc"></h3>';
$navMap = $this->pageRepo->getPageNav($content);
$this->assertCount(1, $navMap);
$this->assertArraySubset([
'nodeName' => 'h1',
'link' => '#testa',
'text' => 'Hello'
], $navMap[0]);
}
}

View File

@@ -1 +1 @@
v0.26.0
v0.26.3