mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-02-17 19:06:49 +03:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f484fbc110 | ||
|
|
299d3b3149 | ||
|
|
9646339933 | ||
|
|
e4383765e1 | ||
|
|
5d547fcf4c | ||
|
|
826b36c985 | ||
|
|
3fa1174e7a | ||
|
|
50e8501027 | ||
|
|
8a221f64e4 | ||
|
|
035be66ebc | ||
|
|
227027fc45 | ||
|
|
0f040fe8b1 | ||
|
|
10ebe53bd9 | ||
|
|
7abc269316 | ||
|
|
f0cf4bd0f8 | ||
|
|
46dcc30bf7 | ||
|
|
9f7d3b55dd | ||
|
|
3e5e88dc87 | ||
|
|
c77a0fdff3 | ||
|
|
6a63b38bb3 | ||
|
|
ed4baed28c | ||
|
|
90d011fc15 | ||
|
|
ff59bbdc07 | ||
|
|
4dc443b7df | ||
|
|
19f02d927e | ||
|
|
da7bedd2e4 | ||
|
|
20db372596 | ||
|
|
43eed1660c | ||
|
|
e6b754fad0 | ||
|
|
018de5def3 | ||
|
|
5c4fc3dc2c | ||
|
|
805fd98c0f | ||
|
|
fcbae16730 | ||
|
|
07ec880e33 | ||
|
|
ab436ed5c3 | ||
|
|
082befb2fc | ||
|
|
b0a8cb0c5d | ||
|
|
b08d1b36de | ||
|
|
88d86df66f |
@@ -351,10 +351,25 @@ EXPORT_PDF_COMMAND_TIMEOUT=15
|
||||
# Only used if 'ALLOW_UNTRUSTED_SERVER_FETCHING=true' which disables security protections.
|
||||
WKHTMLTOPDF=false
|
||||
|
||||
# Allow <script> tags in page content
|
||||
# Allow JavaScript, and other potentiall dangerous content in page content.
|
||||
# This also removes CSP-level JavaScript control.
|
||||
# Note, if set to 'true' the page editor may still escape scripts.
|
||||
# DEPRECATED: Use 'APP_CONTENT_FILTERING' instead as detailed below. Activiting this option
|
||||
# effectively sets APP_CONTENT_FILTERING='' (No filtering)
|
||||
ALLOW_CONTENT_SCRIPTS=false
|
||||
|
||||
# Control the behaviour of content filtering, primarily used for page content.
|
||||
# This setting is a string of characters which represent different available filters:
|
||||
# - j - Filter out JavaScript and unknown binary data based content
|
||||
# - h - Filter out unexpected, and potentially dangerous, HTML elements
|
||||
# - f - Filter out unexpected form elements
|
||||
# - a - Run content through a more complex allowlist filter
|
||||
# This defaults to using all filters, unless ALLOW_CONTENT_SCRIPTS is set to true in which case no filters are used.
|
||||
# Note: These filters are a best-attempt and may not be 100% effective. They are typically a layer used in addition to other security measures.
|
||||
# Note: The default value will always be the most-strict, so it's advised to leave this unset in your own configuration
|
||||
# to ensure you are always using the full range of filters.
|
||||
APP_CONTENT_FILTERING="jfha"
|
||||
|
||||
# Indicate if robots/crawlers should crawl your instance.
|
||||
# Can be 'true', 'false' or 'null'.
|
||||
# The behaviour of the default 'null' option will depend on the 'app-public' admin setting.
|
||||
|
||||
11
.github/translators.txt
vendored
11
.github/translators.txt
vendored
@@ -519,3 +519,14 @@ Tahsin Ahmed (tahsinahmed2012) :: Bengali
|
||||
bojan_che :: Serbian (Cyrillic)
|
||||
setiawan setiawan (culture.setiawan) :: Indonesian
|
||||
Donald Mac Kenzie (kiuman) :: Norwegian Bokmal
|
||||
Gabriel Silver (GabrielBSilver) :: Hebrew
|
||||
Tomas Darius Davainis (Tomasdd) :: Lithuanian
|
||||
CriedHero :: Chinese Simplified
|
||||
Henrik (henrik2105) :: Norwegian Bokmal
|
||||
FoW (fofwisdom) :: Korean
|
||||
serinf-lauza :: French
|
||||
Diyan Nikolaev (nikolaev.diyan) :: Bulgarian
|
||||
Shadluk Avan (quldosh) :: Uzbek
|
||||
Marci (MartonPoto) :: Hungarian
|
||||
Michał Sadurski (wheeskeey) :: Polish
|
||||
JanDziaslo :: Polish
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2025, Dan Brown and the BookStack project contributors.
|
||||
Copyright (c) 2015-2026, Dan Brown and the BookStack project contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -8,6 +8,7 @@ use BookStack\Permissions\PermissionApplicator;
|
||||
use BookStack\Users\Models\HasCreatorAndUpdater;
|
||||
use BookStack\Users\Models\OwnableInterface;
|
||||
use BookStack\Util\HtmlContentFilter;
|
||||
use BookStack\Util\HtmlContentFilterConfig;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -82,7 +83,8 @@ class Comment extends Model implements Loggable, OwnableInterface
|
||||
|
||||
public function safeHtml(): string
|
||||
{
|
||||
return HtmlContentFilter::removeScriptsFromHtmlString($this->html ?? '');
|
||||
$filter = new HtmlContentFilter(new HtmlContentFilterConfig());
|
||||
return $filter->filterString($this->html ?? '');
|
||||
}
|
||||
|
||||
public function jointPermissions(): HasMany
|
||||
|
||||
@@ -37,10 +37,15 @@ return [
|
||||
// The limit for all uploaded files, including images and attachments in MB.
|
||||
'upload_limit' => env('FILE_UPLOAD_SIZE_LIMIT', 50),
|
||||
|
||||
// Allow <script> tags to entered within page content.
|
||||
// <script> tags are escaped by default.
|
||||
// Even when overridden the WYSIWYG editor may still escape script content.
|
||||
'allow_content_scripts' => env('ALLOW_CONTENT_SCRIPTS', false),
|
||||
// Control the behaviour of content filtering, primarily used for page content.
|
||||
// This setting is a string of characters which represent different available filters:
|
||||
// - j - Filter out JavaScript and unknown binary data based content
|
||||
// - h - Filter out unexpected, and potentially dangerous, HTML elements
|
||||
// - f - Filter out unexpected form elements
|
||||
// - a - Run content through a more complex allowlist filter
|
||||
// This defaults to using all filters, unless ALLOW_CONTENT_SCRIPTS is set to true in which case no filters are used.
|
||||
// Note: These filters are a best-attempt and may not be 100% effective. They are typically a layer used in addition to other security measures.
|
||||
'content_filtering' => env('APP_CONTENT_FILTERING', env('ALLOW_CONTENT_SCRIPTS', false) === true ? '' : 'jhfa'),
|
||||
|
||||
// Allow server-side fetches to be performed to potentially unknown
|
||||
// and user-provided locations. Primarily used in exports when loading
|
||||
@@ -48,8 +53,8 @@ return [
|
||||
'allow_untrusted_server_fetching' => env('ALLOW_UNTRUSTED_SERVER_FETCHING', false),
|
||||
|
||||
// Override the default behaviour for allowing crawlers to crawl the instance.
|
||||
// May be ignored if view has be overridden or modified.
|
||||
// Defaults to null since, if not set, 'app-public' status used instead.
|
||||
// May be ignored if the underlying view has been overridden or modified.
|
||||
// Defaults to null in which case the 'app-public' status is used instead.
|
||||
'allow_robots' => env('ALLOW_ROBOTS', null),
|
||||
|
||||
// Application Base URL, Used by laravel in development commands
|
||||
|
||||
@@ -21,6 +21,8 @@ use BookStack\Exceptions\PermissionsException;
|
||||
use BookStack\Http\Controller;
|
||||
use BookStack\Permissions\Permission;
|
||||
use BookStack\References\ReferenceFetcher;
|
||||
use BookStack\Util\HtmlContentFilter;
|
||||
use BookStack\Util\HtmlContentFilterConfig;
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -173,7 +175,7 @@ class PageController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Get page from an ajax request.
|
||||
* Get a page from an ajax request.
|
||||
*
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
@@ -183,6 +185,10 @@ class PageController extends Controller
|
||||
$page->setHidden(array_diff($page->getHidden(), ['html', 'markdown']));
|
||||
$page->makeHidden(['book']);
|
||||
|
||||
$filterConfig = HtmlContentFilterConfig::fromConfigString(config('app.content_filtering'));
|
||||
$filter = new HtmlContentFilter($filterConfig);
|
||||
$page->html = $filter->filterString($page->html);
|
||||
|
||||
return response()->json($page);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use BookStack\Entities\Models\Book;
|
||||
use BookStack\Entities\Models\Bookshelf;
|
||||
use BookStack\Entities\Models\Chapter;
|
||||
use BookStack\Util\HtmlContentFilter;
|
||||
use BookStack\Util\HtmlContentFilterConfig;
|
||||
|
||||
class EntityHtmlDescription
|
||||
{
|
||||
@@ -50,7 +51,8 @@ class EntityHtmlDescription
|
||||
return $html;
|
||||
}
|
||||
|
||||
return HtmlContentFilter::removeScriptsFromHtmlString($html);
|
||||
$filter = new HtmlContentFilter(new HtmlContentFilterConfig());
|
||||
return $filter->filterString($html);
|
||||
}
|
||||
|
||||
public function getPlain(): string
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace BookStack\Entities\Tools;
|
||||
|
||||
use BookStack\App\AppVersion;
|
||||
use BookStack\Entities\Models\Page;
|
||||
use BookStack\Entities\Queries\PageQueries;
|
||||
use BookStack\Entities\Tools\Markdown\MarkdownToHtml;
|
||||
@@ -13,6 +14,7 @@ use BookStack\Uploads\ImageRepo;
|
||||
use BookStack\Uploads\ImageService;
|
||||
use BookStack\Users\Models\User;
|
||||
use BookStack\Util\HtmlContentFilter;
|
||||
use BookStack\Util\HtmlContentFilterConfig;
|
||||
use BookStack\Util\HtmlDocument;
|
||||
use BookStack\Util\WebSafeMimeSniffer;
|
||||
use Closure;
|
||||
@@ -317,11 +319,30 @@ class PageContent
|
||||
$this->updateIdsRecursively($doc->getBody(), 0, $idMap, $changeMap);
|
||||
}
|
||||
|
||||
if (!config('app.allow_content_scripts')) {
|
||||
HtmlContentFilter::removeScriptsFromDocument($doc);
|
||||
$cacheKey = $this->getContentCacheKey($doc->getBodyInnerHtml());
|
||||
$cached = cache()->get($cacheKey, null);
|
||||
if ($cached !== null) {
|
||||
return $cached;
|
||||
}
|
||||
|
||||
return $doc->getBodyInnerHtml();
|
||||
$filterConfig = HtmlContentFilterConfig::fromConfigString(config('app.content_filtering'));
|
||||
$filter = new HtmlContentFilter($filterConfig);
|
||||
$filtered = $filter->filterDocument($doc);
|
||||
|
||||
$cacheTime = 86400 * 7; // 1 week
|
||||
cache()->put($cacheKey, $filtered, $cacheTime);
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
protected function getContentCacheKey(string $html): string
|
||||
{
|
||||
$contentHash = md5($html);
|
||||
$contentId = $this->page->id;
|
||||
$contentTime = $this->page->updated_at?->timestamp ?? time();
|
||||
$appVersion = AppVersion::get();
|
||||
$filterConfig = config('app.content_filtering') ?? '';
|
||||
return "page-content-cache::{$filterConfig}::{$appVersion}::{$contentId}::{$contentTime}::{$contentHash}";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,8 @@ use BookStack\Entities\Queries\EntityQueries;
|
||||
use BookStack\Entities\Tools\Markdown\HtmlToMarkdown;
|
||||
use BookStack\Entities\Tools\Markdown\MarkdownToHtml;
|
||||
use BookStack\Permissions\Permission;
|
||||
use BookStack\Util\HtmlContentFilter;
|
||||
use BookStack\Util\HtmlContentFilterConfig;
|
||||
|
||||
class PageEditorData
|
||||
{
|
||||
@@ -47,6 +49,7 @@ class PageEditorData
|
||||
$isDraftRevision = false;
|
||||
$this->warnings = [];
|
||||
$editActivity = new PageEditActivity($page);
|
||||
$lastEditorId = $page->updated_by ?? user()->id;
|
||||
|
||||
if ($editActivity->hasActiveEditing()) {
|
||||
$this->warnings[] = $editActivity->activeEditingMessage();
|
||||
@@ -58,11 +61,20 @@ class PageEditorData
|
||||
$page->forceFill($userDraft->only(['name', 'html', 'markdown']));
|
||||
$isDraftRevision = true;
|
||||
$this->warnings[] = $editActivity->getEditingActiveDraftMessage($userDraft);
|
||||
$lastEditorId = $userDraft->created_by;
|
||||
}
|
||||
|
||||
// Get editor type and handle changes
|
||||
$editorType = $this->getEditorType($page);
|
||||
$this->updateContentForEditor($page, $editorType);
|
||||
|
||||
// Filter HTML content if required
|
||||
if ($editorType->isHtmlBased() && !old('html') && $lastEditorId !== user()->id) {
|
||||
$filterConfig = HtmlContentFilterConfig::fromConfigString(config('app.content_filtering'));
|
||||
$filter = new HtmlContentFilter($filterConfig);
|
||||
$page->html = $filter->filterString($page->html);
|
||||
}
|
||||
|
||||
return [
|
||||
'page' => $page,
|
||||
'book' => $page->book,
|
||||
|
||||
@@ -58,6 +58,16 @@ class ZipExportReader
|
||||
{
|
||||
$this->open();
|
||||
|
||||
$info = $this->zip->statName('data.json');
|
||||
if ($info === false) {
|
||||
throw new ZipExportException(trans('errors.import_zip_cant_decode_data'));
|
||||
}
|
||||
|
||||
$maxSize = max(intval(config()->get('app.upload_limit')), 1) * 1000000;
|
||||
if ($info['size'] > $maxSize) {
|
||||
throw new ZipExportException(trans('errors.import_zip_data_too_large'));
|
||||
}
|
||||
|
||||
// Validate json data exists, including metadata
|
||||
$jsonData = $this->zip->getFromName('data.json') ?: '';
|
||||
$importData = json_decode($jsonData, true);
|
||||
@@ -73,6 +83,17 @@ class ZipExportReader
|
||||
return $this->zip->statName("files/{$fileName}") !== false;
|
||||
}
|
||||
|
||||
public function fileWithinSizeLimit(string $fileName): bool
|
||||
{
|
||||
$fileInfo = $this->zip->statName("files/{$fileName}");
|
||||
if ($fileInfo === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$maxSize = max(intval(config()->get('app.upload_limit')), 1) * 1000000;
|
||||
return $fileInfo['size'] <= $maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false|resource
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,6 @@ class ZipFileReferenceRule implements ValidationRule
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -23,6 +22,13 @@ class ZipFileReferenceRule implements ValidationRule
|
||||
$fail('validation.zip_file')->translate();
|
||||
}
|
||||
|
||||
if (!$this->context->zipReader->fileWithinSizeLimit($value)) {
|
||||
$fail('validation.zip_file_size')->translate([
|
||||
'attribute' => $value,
|
||||
'size' => config('app.upload_limit'),
|
||||
]);
|
||||
}
|
||||
|
||||
if (!empty($this->acceptedMimes)) {
|
||||
$fileMime = $this->context->zipReader->sniffFileMime($value);
|
||||
if (!in_array($fileMime, $this->acceptedMimes)) {
|
||||
|
||||
@@ -265,6 +265,12 @@ class ZipImportRunner
|
||||
|
||||
protected function zipFileToUploadedFile(string $fileName, ZipExportReader $reader): UploadedFile
|
||||
{
|
||||
if (!$reader->fileWithinSizeLimit($fileName)) {
|
||||
throw new ZipImportException([
|
||||
"File $fileName exceeds app upload limit."
|
||||
]);
|
||||
}
|
||||
|
||||
$tempPath = tempnam(sys_get_temp_dir(), 'bszipextract');
|
||||
$fileStream = $reader->streamFile($fileName);
|
||||
$tempStream = fopen($tempPath, 'wb');
|
||||
|
||||
@@ -17,7 +17,7 @@ class ApiAuthenticate
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
// Validate the token and it's users API access
|
||||
$this->ensureAuthorizedBySessionOrToken();
|
||||
$this->ensureAuthorizedBySessionOrToken($request);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -28,22 +28,28 @@ class ApiAuthenticate
|
||||
*
|
||||
* @throws ApiAuthException
|
||||
*/
|
||||
protected function ensureAuthorizedBySessionOrToken(): void
|
||||
protected function ensureAuthorizedBySessionOrToken(Request $request): void
|
||||
{
|
||||
// Return if the user is already found to be signed in via session-based auth.
|
||||
// This is to make it easy to browser the API via browser after just logging into the system.
|
||||
if (!user()->isGuest() || session()->isStarted()) {
|
||||
// Use the active user session already exists.
|
||||
// This is to make it easy to explore API endpoints via the UI.
|
||||
if (session()->isStarted()) {
|
||||
// Ensure the user has API access permission
|
||||
if (!$this->sessionUserHasApiAccess()) {
|
||||
throw new ApiAuthException(trans('errors.api_user_no_api_permission'), 403);
|
||||
}
|
||||
|
||||
// Only allow GET requests for cookie-based API usage
|
||||
if ($request->method() !== 'GET') {
|
||||
throw new ApiAuthException(trans('errors.api_cookie_auth_only_get'), 403);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Set our api guard to be the default for this request lifecycle.
|
||||
auth()->shouldUse('api');
|
||||
|
||||
// Validate the token and it's users API access
|
||||
// Validate the token and its users API access
|
||||
auth()->authenticate();
|
||||
}
|
||||
|
||||
|
||||
@@ -78,8 +78,9 @@ class SearchController extends Controller
|
||||
|
||||
// Search for entities otherwise show most popular
|
||||
if ($searchTerm !== false) {
|
||||
$searchTerm .= ' {type:' . implode('|', $entityTypes) . '}';
|
||||
$entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 20)['results'];
|
||||
$options = SearchOptions::fromString($searchTerm);
|
||||
$options->setFilter('type', implode('|', $entityTypes));
|
||||
$entities = $this->searchRunner->searchEntities($options, 'all', 1, 20)['results'];
|
||||
} else {
|
||||
$entities = $queryPopular->run(20, 0, $entityTypes);
|
||||
}
|
||||
|
||||
@@ -82,4 +82,12 @@ class SearchOptionSet
|
||||
$values = array_values(array_filter($this->options, fn (SearchOption $option) => !$option->negated));
|
||||
return new self($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self<T>
|
||||
*/
|
||||
public function limit(int $limit): self
|
||||
{
|
||||
return new self(array_slice(array_values($this->options), 0, $limit));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ class SearchOptions
|
||||
{
|
||||
$instance = new self();
|
||||
$instance->addOptionsFromString($search);
|
||||
$instance->limitOptions();
|
||||
return $instance;
|
||||
}
|
||||
|
||||
@@ -87,6 +88,8 @@ class SearchOptions
|
||||
$instance->filters = $instance->filters->merge($extras->filters);
|
||||
}
|
||||
|
||||
$instance->limitOptions();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
@@ -147,6 +150,25 @@ class SearchOptions
|
||||
$this->filters = $this->filters->merge(new SearchOptionSet($terms['filters']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the amount of search options to reasonable levels.
|
||||
* Provides higher limits to logged-in users since that signals a slightly
|
||||
* higher level of trust.
|
||||
*/
|
||||
protected function limitOptions(): void
|
||||
{
|
||||
$userLoggedIn = !user()->isGuest();
|
||||
$searchLimit = $userLoggedIn ? 10 : 5;
|
||||
$exactLimit = $userLoggedIn ? 4 : 2;
|
||||
$tagLimit = $userLoggedIn ? 8 : 4;
|
||||
$filterLimit = $userLoggedIn ? 10 : 5;
|
||||
|
||||
$this->searches = $this->searches->limit($searchLimit);
|
||||
$this->exacts = $this->exacts->limit($exactLimit);
|
||||
$this->tags = $this->tags->limit($tagLimit);
|
||||
$this->filters = $this->filters->limit($filterLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode backslash escaping within the input string.
|
||||
*/
|
||||
|
||||
@@ -4,25 +4,16 @@ namespace BookStack\Theming;
|
||||
|
||||
use BookStack\Util\CspService;
|
||||
use BookStack\Util\HtmlContentFilter;
|
||||
use BookStack\Util\HtmlContentFilterConfig;
|
||||
use BookStack\Util\HtmlNonceApplicator;
|
||||
use Illuminate\Contracts\Cache\Repository as Cache;
|
||||
|
||||
class CustomHtmlHeadContentProvider
|
||||
{
|
||||
/**
|
||||
* @var CspService
|
||||
*/
|
||||
protected $cspService;
|
||||
|
||||
/**
|
||||
* @var Cache
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
public function __construct(CspService $cspService, Cache $cache)
|
||||
{
|
||||
$this->cspService = $cspService;
|
||||
$this->cache = $cache;
|
||||
public function __construct(
|
||||
protected CspService $cspService,
|
||||
protected Cache $cache
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +41,8 @@ class CustomHtmlHeadContentProvider
|
||||
$hash = md5($content);
|
||||
|
||||
return $this->cache->remember('custom-head-export:' . $hash, 86400, function () use ($content) {
|
||||
return HtmlContentFilter::removeScriptsFromHtmlString($content);
|
||||
$config = new HtmlContentFilterConfig(filterOutNonContentElements: false, useAllowListFilter: false);
|
||||
return (new HtmlContentFilter($config))->filterString($content);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
131
app/Util/ConfiguredHtmlPurifier.php
Normal file
131
app/Util/ConfiguredHtmlPurifier.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Util;
|
||||
|
||||
use BookStack\App\AppVersion;
|
||||
use HTMLPurifier;
|
||||
use HTMLPurifier_Config;
|
||||
use HTMLPurifier_DefinitionCache_Serializer;
|
||||
use HTMLPurifier_HTML5Config;
|
||||
use HTMLPurifier_HTMLDefinition;
|
||||
|
||||
/**
|
||||
* Provides a configured HTML Purifier instance.
|
||||
* https://github.com/ezyang/htmlpurifier
|
||||
* Also uses this to extend support to HTML5 elements:
|
||||
* https://github.com/xemlock/htmlpurifier-html5
|
||||
*/
|
||||
class ConfiguredHtmlPurifier
|
||||
{
|
||||
protected HTMLPurifier $purifier;
|
||||
protected static bool $cachedChecked = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$config = HTMLPurifier_HTML5Config::createDefault();
|
||||
$this->setConfig($config);
|
||||
$this->resetCacheIfNeeded($config);
|
||||
|
||||
$htmlDef = $config->getDefinition('HTML', true, true);
|
||||
if ($htmlDef instanceof HTMLPurifier_HTMLDefinition) {
|
||||
$this->configureDefinition($htmlDef);
|
||||
}
|
||||
|
||||
$this->purifier = new HTMLPurifier($config);
|
||||
}
|
||||
|
||||
protected function resetCacheIfNeeded(HTMLPurifier_Config $config): void
|
||||
{
|
||||
if (self::$cachedChecked) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cachedForVersion = cache('htmlpurifier::cache-version');
|
||||
$appVersion = AppVersion::get();
|
||||
if ($cachedForVersion !== $appVersion) {
|
||||
foreach (['HTML', 'CSS', 'URI'] as $name) {
|
||||
$cache = new HTMLPurifier_DefinitionCache_Serializer($name);
|
||||
$cache->flush($config);
|
||||
}
|
||||
cache()->set('htmlpurifier::cache-version', $appVersion);
|
||||
}
|
||||
|
||||
self::$cachedChecked = true;
|
||||
}
|
||||
|
||||
protected function setConfig(HTMLPurifier_Config $config): void
|
||||
{
|
||||
$config->set('Cache.SerializerPath', storage_path('framework/purifier'));
|
||||
$config->set('Core.AllowHostnameUnderscore', true);
|
||||
$config->set('CSS.AllowTricky', true);
|
||||
$config->set('HTML.SafeIframe', true);
|
||||
$config->set('Attr.EnableID', true);
|
||||
$config->set('Attr.ID.HTML5', true);
|
||||
$config->set('Output.FixInnerHTML', false);
|
||||
$config->set('URI.SafeIframeRegexp', '%^(http://|https://|//)%');
|
||||
$config->set('URI.AllowedSchemes', [
|
||||
'http' => true,
|
||||
'https' => true,
|
||||
'mailto' => true,
|
||||
'ftp' => true,
|
||||
'nntp' => true,
|
||||
'news' => true,
|
||||
'tel' => true,
|
||||
'file' => true,
|
||||
]);
|
||||
|
||||
// $config->set('Cache.DefinitionImpl', null); // Disable cache during testing
|
||||
}
|
||||
|
||||
public function configureDefinition(HTMLPurifier_HTMLDefinition $definition): void
|
||||
{
|
||||
// Allow the object element
|
||||
$definition->addElement(
|
||||
'object',
|
||||
'Inline',
|
||||
'Flow',
|
||||
'Common',
|
||||
[
|
||||
'data' => 'URI',
|
||||
'type' => 'Text',
|
||||
'width' => 'Length',
|
||||
'height' => 'Length',
|
||||
]
|
||||
);
|
||||
|
||||
// Allow the embed element
|
||||
$definition->addElement(
|
||||
'embed',
|
||||
'Inline',
|
||||
'Empty',
|
||||
'Common',
|
||||
[
|
||||
'src' => 'URI',
|
||||
'type' => 'Text',
|
||||
'width' => 'Length',
|
||||
'height' => 'Length',
|
||||
]
|
||||
);
|
||||
|
||||
// Allow checkbox inputs
|
||||
$definition->addElement(
|
||||
'input',
|
||||
'Formctrl',
|
||||
'Empty',
|
||||
'Common',
|
||||
[
|
||||
'checked' => 'Bool#checked',
|
||||
'disabled' => 'Bool#disabled',
|
||||
'name' => 'Text',
|
||||
'readonly' => 'Bool#readonly',
|
||||
'type' => 'Enum#checkbox',
|
||||
'value' => 'Text',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function purify(string $html): string
|
||||
{
|
||||
return $this->purifier->purify($html);
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ class CspService
|
||||
*/
|
||||
protected function getScriptSrc(): string
|
||||
{
|
||||
if (config('app.allow_content_scripts')) {
|
||||
if ($this->scriptFilteringDisabled()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ class CspService
|
||||
*/
|
||||
protected function getObjectSrc(): string
|
||||
{
|
||||
if (config('app.allow_content_scripts')) {
|
||||
if ($this->scriptFilteringDisabled()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -124,6 +124,11 @@ class CspService
|
||||
return "base-uri 'self'";
|
||||
}
|
||||
|
||||
protected function scriptFilteringDisabled(): bool
|
||||
{
|
||||
return !HtmlContentFilterConfig::fromConfigString(config('app.content_filtering'))->filterOutJavaScript;
|
||||
}
|
||||
|
||||
protected function getAllowedIframeHosts(): array
|
||||
{
|
||||
$hosts = config('app.iframe_hosts') ?? '';
|
||||
|
||||
@@ -8,10 +8,46 @@ use DOMNodeList;
|
||||
|
||||
class HtmlContentFilter
|
||||
{
|
||||
/**
|
||||
* Remove all the script elements from the given HTML document.
|
||||
*/
|
||||
public static function removeScriptsFromDocument(HtmlDocument $doc)
|
||||
public function __construct(
|
||||
protected HtmlContentFilterConfig $config
|
||||
) {
|
||||
}
|
||||
|
||||
public function filterDocument(HtmlDocument $doc): string
|
||||
{
|
||||
if ($this->config->filterOutJavaScript) {
|
||||
$this->filterOutScriptsFromDocument($doc);
|
||||
}
|
||||
if ($this->config->filterOutFormElements) {
|
||||
$this->filterOutFormElementsFromDocument($doc);
|
||||
}
|
||||
if ($this->config->filterOutBadHtmlElements) {
|
||||
$this->filterOutBadHtmlElementsFromDocument($doc);
|
||||
}
|
||||
if ($this->config->filterOutNonContentElements) {
|
||||
$this->filterOutNonContentElementsFromDocument($doc);
|
||||
}
|
||||
|
||||
$filtered = $doc->getBodyInnerHtml();
|
||||
if ($this->config->useAllowListFilter) {
|
||||
$filtered = $this->applyAllowListFiltering($filtered);
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
public function filterString(string $html): string
|
||||
{
|
||||
return $this->filterDocument(new HtmlDocument($html));
|
||||
}
|
||||
|
||||
protected function applyAllowListFiltering(string $html): string
|
||||
{
|
||||
$purifier = new ConfiguredHtmlPurifier();
|
||||
return $purifier->purify($html);
|
||||
}
|
||||
|
||||
protected function filterOutScriptsFromDocument(HtmlDocument $doc): void
|
||||
{
|
||||
// Remove standard script tags
|
||||
$scriptElems = $doc->queryXPath('//script');
|
||||
@@ -21,21 +57,21 @@ class HtmlContentFilter
|
||||
$badLinks = $doc->queryXPath('//*[' . static::xpathContains('@href', 'javascript:') . ']');
|
||||
static::removeNodes($badLinks);
|
||||
|
||||
// Remove forms with calls to JavaScript URI
|
||||
// Remove elements with form-like attributes with calls to JavaScript URI
|
||||
$badForms = $doc->queryXPath('//*[' . static::xpathContains('@action', 'javascript:') . '] | //*[' . static::xpathContains('@formaction', 'javascript:') . ']');
|
||||
static::removeNodes($badForms);
|
||||
|
||||
// Remove meta tag to prevent external redirects
|
||||
$metaTags = $doc->queryXPath('//meta[' . static::xpathContains('@content', 'url') . ']');
|
||||
static::removeNodes($metaTags);
|
||||
|
||||
// Remove data or JavaScript iFrames
|
||||
// Remove data or JavaScript iFrames & embeds
|
||||
$badIframes = $doc->queryXPath('//*[' . static::xpathContains('@src', 'data:') . '] | //*[' . static::xpathContains('@src', 'javascript:') . '] | //*[@srcdoc]');
|
||||
static::removeNodes($badIframes);
|
||||
|
||||
// Remove data or JavaScript objects
|
||||
$badObjects = $doc->queryXPath('//*[' . static::xpathContains('@data', 'data:') . '] | //*[' . static::xpathContains('@data', 'javascript:') . ']');
|
||||
static::removeNodes($badObjects);
|
||||
|
||||
// Remove attributes, within svg children, hiding JavaScript or data uris.
|
||||
// A bunch of svg element and attribute combinations expose xss possibilities.
|
||||
// For example, SVG animate tag can exploit javascript in values.
|
||||
// For example, SVG animate tag can exploit JavaScript in values.
|
||||
$badValuesAttrs = $doc->queryXPath('//svg//@*[' . static::xpathContains('.', 'data:') . '] | //svg//@*[' . static::xpathContains('.', 'javascript:') . ']');
|
||||
static::removeAttributes($badValuesAttrs);
|
||||
|
||||
@@ -49,23 +85,52 @@ class HtmlContentFilter
|
||||
static::removeAttributes($onAttributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove scripts from the given HTML string.
|
||||
*/
|
||||
public static function removeScriptsFromHtmlString(string $html): string
|
||||
protected function filterOutFormElementsFromDocument(HtmlDocument $doc): void
|
||||
{
|
||||
if (empty($html)) {
|
||||
return $html;
|
||||
// Remove form elements
|
||||
$formElements = ['form', 'fieldset', 'button', 'textarea', 'select'];
|
||||
foreach ($formElements as $formElement) {
|
||||
$matchingFormElements = $doc->queryXPath('//' . $formElement);
|
||||
static::removeNodes($matchingFormElements);
|
||||
}
|
||||
|
||||
$doc = new HtmlDocument($html);
|
||||
static::removeScriptsFromDocument($doc);
|
||||
// Remove non-checkbox inputs
|
||||
$inputsToRemove = $doc->queryXPath('//input');
|
||||
/** @var DOMElement $input */
|
||||
foreach ($inputsToRemove as $input) {
|
||||
$type = strtolower($input->getAttribute('type'));
|
||||
if ($type !== 'checkbox') {
|
||||
$input->parentNode->removeChild($input);
|
||||
}
|
||||
}
|
||||
|
||||
return $doc->getBodyInnerHtml();
|
||||
// Remove form attributes
|
||||
$formAttrs = ['form', 'formaction', 'formmethod', 'formtarget'];
|
||||
foreach ($formAttrs as $formAttr) {
|
||||
$matchingFormAttrs = $doc->queryXPath('//@' . $formAttr);
|
||||
static::removeAttributes($matchingFormAttrs);
|
||||
}
|
||||
}
|
||||
|
||||
protected function filterOutBadHtmlElementsFromDocument(HtmlDocument $doc): void
|
||||
{
|
||||
// Remove meta tag to prevent external redirects
|
||||
$metaTags = $doc->queryXPath('//meta[' . static::xpathContains('@content', 'url') . ']');
|
||||
static::removeNodes($metaTags);
|
||||
}
|
||||
|
||||
protected function filterOutNonContentElementsFromDocument(HtmlDocument $doc): void
|
||||
{
|
||||
// Remove non-content elements
|
||||
$formElements = ['link', 'style', 'meta', 'title', 'template'];
|
||||
foreach ($formElements as $formElement) {
|
||||
$matchingFormElements = $doc->queryXPath('//' . $formElement);
|
||||
static::removeNodes($matchingFormElements);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a xpath contains statement with a translation automatically built within
|
||||
* Create an x-path 'contains' statement with a translation automatically built within
|
||||
* to affectively search in a cases-insensitive manner.
|
||||
*/
|
||||
protected static function xpathContains(string $property, string $value): string
|
||||
@@ -99,4 +164,34 @@ class HtmlContentFilter
|
||||
$parentNode->removeAttribute($attrName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias using the old method name to avoid potential compatibility breaks during patch release.
|
||||
* To remove in future feature release.
|
||||
* @deprecated Use filterDocument instead.
|
||||
*/
|
||||
public static function removeScriptsFromDocument(HtmlDocument $doc): void
|
||||
{
|
||||
$config = new HtmlContentFilterConfig(
|
||||
filterOutNonContentElements: false,
|
||||
useAllowListFilter: false,
|
||||
);
|
||||
$filter = new self($config);
|
||||
$filter->filterDocument($doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias using the old method name to avoid potential compatibility breaks during patch release.
|
||||
* To remove in future feature release.
|
||||
* @deprecated Use filterString instead.
|
||||
*/
|
||||
public static function removeScriptsFromHtmlString(string $html): string
|
||||
{
|
||||
$config = new HtmlContentFilterConfig(
|
||||
filterOutNonContentElements: false,
|
||||
useAllowListFilter: false,
|
||||
);
|
||||
$filter = new self($config);
|
||||
return $filter->filterString($html);
|
||||
}
|
||||
}
|
||||
|
||||
31
app/Util/HtmlContentFilterConfig.php
Normal file
31
app/Util/HtmlContentFilterConfig.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Util;
|
||||
|
||||
readonly class HtmlContentFilterConfig
|
||||
{
|
||||
public function __construct(
|
||||
public bool $filterOutJavaScript = true,
|
||||
public bool $filterOutBadHtmlElements = true,
|
||||
public bool $filterOutFormElements = true,
|
||||
public bool $filterOutNonContentElements = true,
|
||||
public bool $useAllowListFilter = true,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance from a config string, where the string
|
||||
* is a combination of characters to enable filters.
|
||||
*/
|
||||
public static function fromConfigString(string $config): self
|
||||
{
|
||||
$config = strtolower($config);
|
||||
return new self(
|
||||
filterOutJavaScript: str_contains($config, 'j'),
|
||||
filterOutBadHtmlElements: str_contains($config, 'h'),
|
||||
filterOutFormElements: str_contains($config, 'f'),
|
||||
filterOutNonContentElements: str_contains($config, 'h'),
|
||||
useAllowListFilter: str_contains($config, 'a'),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
"ext-zip": "*",
|
||||
"bacon/bacon-qr-code": "^3.0",
|
||||
"dompdf/dompdf": "^3.1",
|
||||
"ezyang/htmlpurifier": "^4.19",
|
||||
"guzzlehttp/guzzle": "^7.4",
|
||||
"intervention/image": "^3.5",
|
||||
"knplabs/knp-snappy": "^1.5",
|
||||
@@ -38,7 +39,8 @@
|
||||
"socialiteproviders/microsoft-azure": "^5.1",
|
||||
"socialiteproviders/okta": "^4.2",
|
||||
"socialiteproviders/twitch": "^5.3",
|
||||
"ssddanbrown/htmldiff": "^2.0.0"
|
||||
"ssddanbrown/htmldiff": "^2.0.0",
|
||||
"xemlock/htmlpurifier-html5": "^0.1.12"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.21",
|
||||
|
||||
1022
composer.lock
generated
1022
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
project_id: "377219"
|
||||
project_identifier: bookstack
|
||||
base_path: .
|
||||
preserve_hierarchy: false
|
||||
|
||||
@@ -1 +1 @@
|
||||
1b42490f844df68cfd0194d16ca4e40dc82bd50256236d5dee516820dd8271ac
|
||||
5732efe93a37a665ec9e526d713293b438e610dcf0c6e950fa7317907e480252
|
||||
@@ -14,6 +14,9 @@ RUN apt-get update && \
|
||||
wait-for-it && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Mark /app as safe for Git >= 2.35.2
|
||||
RUN git config --system --add safe.directory /app
|
||||
|
||||
# Install PHP extensions
|
||||
RUN docker-php-ext-configure ldap --with-libdir="lib/$(gcc -dumpmachine)" && \
|
||||
docker-php-ext-configure gd --with-freetype --with-jpeg && \
|
||||
|
||||
@@ -98,6 +98,13 @@ Copyright: Copyright (c) 2013-2023 Eduardo Gulias Davis
|
||||
Source: https://github.com/egulias/EmailValidator.git
|
||||
Link: https://github.com/egulias/EmailValidator
|
||||
-----------
|
||||
ezyang/htmlpurifier
|
||||
License: LGPL-2.1-or-later
|
||||
License File: vendor/ezyang/htmlpurifier/LICENSE
|
||||
Copyright: Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
Source: https://github.com/ezyang/htmlpurifier.git
|
||||
Link: http://htmlpurifier.org/
|
||||
-----------
|
||||
firebase/php-jwt
|
||||
License: BSD-3-Clause
|
||||
License File: vendor/firebase/php-jwt/LICENSE
|
||||
@@ -237,21 +244,21 @@ Link: https://config.thephpleague.com
|
||||
league/flysystem
|
||||
License: MIT
|
||||
License File: vendor/league/flysystem/LICENSE
|
||||
Copyright: Copyright (c) 2013-2024 Frank de Jonge
|
||||
Copyright: Copyright (c) 2013-2026 Frank de Jonge
|
||||
Source: https://github.com/thephpleague/flysystem.git
|
||||
Link: https://github.com/thephpleague/flysystem.git
|
||||
-----------
|
||||
league/flysystem-aws-s3-v3
|
||||
License: MIT
|
||||
License File: vendor/league/flysystem-aws-s3-v3/LICENSE
|
||||
Copyright: Copyright (c) 2013-2024 Frank de Jonge
|
||||
Copyright: Copyright (c) 2013-2026 Frank de Jonge
|
||||
Source: https://github.com/thephpleague/flysystem-aws-s3-v3.git
|
||||
Link: https://github.com/thephpleague/flysystem-aws-s3-v3.git
|
||||
-----------
|
||||
league/flysystem-local
|
||||
License: MIT
|
||||
License File: vendor/league/flysystem-local/LICENSE
|
||||
Copyright: Copyright (c) 2013-2024 Frank de Jonge
|
||||
Copyright: Copyright (c) 2013-2026 Frank de Jonge
|
||||
Source: https://github.com/thephpleague/flysystem-local.git
|
||||
Link: https://github.com/thephpleague/flysystem-local.git
|
||||
-----------
|
||||
@@ -323,7 +330,7 @@ License: MIT
|
||||
License File: vendor/nesbot/carbon/LICENSE
|
||||
Copyright: Copyright (C) Brian Nesbitt
|
||||
Source: https://github.com/CarbonPHP/carbon.git
|
||||
Link: https://carbon.nesbot.com
|
||||
Link: https://carbonphp.github.io/carbon/
|
||||
-----------
|
||||
nette/schema
|
||||
License: BSD-3-Clause GPL-2.0-only GPL-3.0-only
|
||||
@@ -465,7 +472,7 @@ Link: https://github.com/php-fig/simple-cache.git
|
||||
psy/psysh
|
||||
License: MIT
|
||||
License File: vendor/psy/psysh/LICENSE
|
||||
Copyright: Copyright (c) 2012-2025 Justin Hileman
|
||||
Copyright: Copyright (c) 2012-2026 Justin Hileman
|
||||
Source: https://github.com/bobthecow/psysh.git
|
||||
Link: https://psysh.org
|
||||
-----------
|
||||
@@ -760,6 +767,13 @@ Copyright: Copyright (c) 2014-present Fabien Potencier
|
||||
Source: https://github.com/symfony/var-dumper.git
|
||||
Link: https://symfony.com
|
||||
-----------
|
||||
thecodingmachine/safe
|
||||
License: MIT
|
||||
License File: vendor/thecodingmachine/safe/LICENSE
|
||||
Copyright: Copyright (c) 2018 TheCodingMachine
|
||||
Source: https://github.com/thecodingmachine/safe.git
|
||||
Link: https://github.com/thecodingmachine/safe.git
|
||||
-----------
|
||||
tijsverkoyen/css-to-inline-styles
|
||||
License: BSD-3-Clause
|
||||
License File: vendor/tijsverkoyen/css-to-inline-styles/LICENSE.md
|
||||
@@ -780,3 +794,10 @@ License File: vendor/voku/portable-ascii/LICENSE.txt
|
||||
Copyright: Copyright (C) 2019 Lars Moelleken
|
||||
Source: https://github.com/voku/portable-ascii.git
|
||||
Link: https://github.com/voku/portable-ascii
|
||||
-----------
|
||||
xemlock/htmlpurifier-html5
|
||||
License: MIT
|
||||
License File: vendor/xemlock/htmlpurifier-html5/LICENSE
|
||||
Copyright: Copyright (c) 2015 Xemlock
|
||||
Source: https://github.com/xemlock/htmlpurifier-html5.git
|
||||
Link: https://github.com/xemlock/htmlpurifier-html5
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'لم أتمكن من قراءة المِلَفّ المضغوط -ZIP-.',
|
||||
'import_zip_cant_decode_data' => 'لم نتمكن من العثور على محتوى المِلَفّ المضغوط data.json وفك تشفيره.',
|
||||
'import_zip_no_data' => 'لا تتضمن بيانات المِلَفّ المضغوط أي محتوى متوقع للكتاب أو الفصل أو الصفحة.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'فشل التحقق من صحة استيراد المِلَفّ المضغوط بسبب الأخطاء التالية:',
|
||||
'import_zip_failed_notification' => 'فشل استيراد المِلَفّ المضغوط.',
|
||||
'import_perms_books' => 'أنت تفتقر إلى الصلاحيات المطلوبة لإنشاء الكتب.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'الشفرة المُقدمة لرمز API المستخدم المحدد غير صحيحة',
|
||||
'api_user_no_api_permission' => 'مالك رمز API المستخدم ليس لديه الصلاحية لإجراء مكالمات API',
|
||||
'api_user_token_expired' => 'انتهت صلاحية رمز الترخيص المستخدم',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'حدث خطأ عند إرسال بريد إلكتروني تجريبي:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'تعذر تحميل الملف. قد لا يقبل الخادم ملفات بهذا الحجم.',
|
||||
|
||||
'zip_file' => ':attribute بحاجة إلى الرجوع إلى مِلَفّ داخل المِلَفّ المضغوط.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => ':attribute بحاجة إلى الإشارة إلى مِلَفّ من نوع :validTypes، وجدت :foundType.',
|
||||
'zip_model_expected' => 'عنصر البيانات المتوقع ولكن ":type" تم العثور عليه.',
|
||||
'zip_unique' => 'يجب أن يكون :attribute فريداً لنوع الكائن داخل المِلَفّ المضغوط.',
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
return [
|
||||
|
||||
'failed' => 'Въведените удостоверителни данни не съвпадат с нашите записи.',
|
||||
'failed' => 'Въведените данни не съвпадат с информацията в системата.',
|
||||
'throttle' => 'Твърде много опити за влизане. Опитайте пак след :seconds секунди.',
|
||||
|
||||
// Login & Register
|
||||
@@ -65,7 +65,7 @@ return [
|
||||
'email_confirm_thanks_desc' => 'Почакайте малко, обработвайки потвърждението ви. Ако не сте пренасочени след 3 секунди, то натиснете долу връзката "Продължаване", за да продължите.',
|
||||
|
||||
'email_not_confirmed' => 'Имейл адресът не е потвърден',
|
||||
'email_not_confirmed_text' => 'Вашият емейл адрес все още не е потвърден.',
|
||||
'email_not_confirmed_text' => 'Вашият имейл адрес все още не е потвърден.',
|
||||
'email_not_confirmed_click_link' => 'Моля да последвате линка, който ви беше изпратен непосредствено след регистрацията.',
|
||||
'email_not_confirmed_resend' => 'Ако не откривате писмото, може да го изпратите отново като попълните формуляра по-долу.',
|
||||
'email_not_confirmed_resend_button' => 'Изпрати отново емейла за потвърждение',
|
||||
@@ -91,7 +91,7 @@ return [
|
||||
'mfa_option_totp_title' => 'Мобилно приложение',
|
||||
'mfa_option_totp_desc' => 'За да използваш многофакторно удостоверяване, ще ти трябва мобилно приложение, което поддържа временни еднократни пароли (TOTP), като например Google Authenticator, Authy или Microsoft Authenticator.',
|
||||
'mfa_option_backup_codes_title' => 'Резервни кодове',
|
||||
'mfa_option_backup_codes_desc' => 'Generates a set of one-time-use backup codes which you\'ll enter on login to verify your identity. Make sure to store these in a safe & secure place.',
|
||||
'mfa_option_backup_codes_desc' => 'Генерира набор от еднократни резервни кодове, които ще въвеждате при влизане, за да потвърдите самоличността си. Уверете се, че ги съхранявате на безопасно и сигурно място.',
|
||||
'mfa_gen_confirm_and_enable' => 'Потвърди и включи',
|
||||
'mfa_gen_backup_codes_title' => 'Настройка на резервни кодове',
|
||||
'mfa_gen_backup_codes_desc' => 'Запази този лист с кодове на сигурно място. Когато достъпваш системата, ще можеш да използваш един от тези кодове като вторичен механизъм за удостоверяване.',
|
||||
|
||||
@@ -6,7 +6,7 @@ return [
|
||||
|
||||
// Buttons
|
||||
'cancel' => 'Отказ',
|
||||
'close' => 'Close',
|
||||
'close' => 'Затвори',
|
||||
'confirm' => 'Потвърждаване',
|
||||
'back' => 'Назад',
|
||||
'save' => 'Запис',
|
||||
@@ -20,7 +20,7 @@ return [
|
||||
'description' => 'Описание',
|
||||
'role' => 'Роля',
|
||||
'cover_image' => 'Образ на корицата',
|
||||
'cover_image_description' => 'This image should be approximately 440x250px although it will be flexibly scaled & cropped to fit the user interface in different scenarios as required, so actual dimensions for display will differ.',
|
||||
'cover_image_description' => 'Изображението трябва да е около 440x250 px. Тъй като ще се мащабира и изрязва автоматично спрямо нуждите на интерфейса, крайните размери при показване може да се различават.',
|
||||
|
||||
// Actions
|
||||
'actions' => 'Действия',
|
||||
@@ -30,8 +30,8 @@ return [
|
||||
'create' => 'Създаване',
|
||||
'update' => 'Обновяване',
|
||||
'edit' => 'Редактиране',
|
||||
'archive' => 'Archive',
|
||||
'unarchive' => 'Un-Archive',
|
||||
'archive' => 'Архивирай',
|
||||
'unarchive' => 'Разархивирай',
|
||||
'sort' => 'Сортиране',
|
||||
'move' => 'Преместване',
|
||||
'copy' => 'Копиране',
|
||||
@@ -44,7 +44,7 @@ return [
|
||||
'remove' => 'Премахване',
|
||||
'add' => 'Добавяне',
|
||||
'configure' => 'Конфигуриране',
|
||||
'manage' => 'Manage',
|
||||
'manage' => 'Управлявай',
|
||||
'fullscreen' => 'Цял екран',
|
||||
'favourite' => 'Любимо',
|
||||
'unfavourite' => 'Не е любимо',
|
||||
@@ -54,7 +54,7 @@ return [
|
||||
'filter_clear' => 'Изчистване на филтрите',
|
||||
'download' => 'Изтегляне',
|
||||
'open_in_tab' => 'Отваряне в раздел',
|
||||
'open' => 'Open',
|
||||
'open' => 'Отвори',
|
||||
|
||||
// Sort Options
|
||||
'sort_options' => 'Опции за сортиране',
|
||||
@@ -111,5 +111,5 @@ return [
|
||||
'terms_of_service' => 'Условия на услугата',
|
||||
|
||||
// OpenSearch
|
||||
'opensearch_description' => 'Search :appName',
|
||||
'opensearch_description' => 'Търси :appName',
|
||||
];
|
||||
|
||||
@@ -13,7 +13,7 @@ return [
|
||||
'cancel' => 'Отказ',
|
||||
'save' => 'Запис',
|
||||
'close' => 'Затваряне',
|
||||
'apply' => 'Apply',
|
||||
'apply' => 'Приложи',
|
||||
'undo' => 'Отмяна',
|
||||
'redo' => 'Повтаряне',
|
||||
'left' => 'Вляво',
|
||||
|
||||
@@ -10,7 +10,7 @@ return [
|
||||
|
||||
// Auth
|
||||
'error_user_exists_different_creds' => 'Потребител с емайл :email вече съществува но с други данни.',
|
||||
'auth_pre_register_theme_prevention' => 'User account could not be registered for the provided details',
|
||||
'auth_pre_register_theme_prevention' => 'Потребителски профил не може да бъде създаден с посочената информация',
|
||||
'email_already_confirmed' => 'Емейлът вече беше потвърден. Моля опитрайте да влезете.',
|
||||
'email_confirmation_invalid' => 'Този код за достъп не е валиден или вече е бил използван, Моля опитай да се регистрираш отново.',
|
||||
'email_confirmation_expired' => 'Кодът за потвърждение изтече, нов емейл за потвърждение беше изпратен.',
|
||||
@@ -37,7 +37,7 @@ return [
|
||||
'social_driver_not_found' => 'Кодът за връзка със социалната мрежа не съществува',
|
||||
'social_driver_not_configured' => 'Социалните настройки на твоя :socialAccount не са конфигурирани правилно.',
|
||||
'invite_token_expired' => 'Твоята покана е изтекла. Вместо това може да пробваш да възстановиш паролата на профила си.',
|
||||
'login_user_not_found' => 'A user for this action could not be found.',
|
||||
'login_user_not_found' => 'Потребител за това действие не може да бъде намерено.',
|
||||
|
||||
// System
|
||||
'path_not_writable' => 'Не може да се качи файл в :filePath. Увери се на сървъра, че в пътя може да се записва.',
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Could not read ZIP file.',
|
||||
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.',
|
||||
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Import ZIP failed to validate with errors:',
|
||||
'import_zip_failed_notification' => 'Failed to import ZIP file.',
|
||||
'import_perms_books' => 'You are lacking the required permissions to create books.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Секретния код, който беше предоставен за достъп до API-а е неправилен',
|
||||
'api_user_no_api_permission' => 'Собственика на АPI кода няма право да прави API заявки',
|
||||
'api_user_token_expired' => 'Кода за достъп, който беше използван, вече не е валиден',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Беше върната грешка, когато се изпрати тестовият емейл:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Файлът не можа да бъде качен. Сървърът може да не приема файлове с такъв размер.',
|
||||
|
||||
'zip_file' => 'The :attribute needs to reference a file within the ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Could not read ZIP file.',
|
||||
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.',
|
||||
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Import ZIP failed to validate with errors:',
|
||||
'import_zip_failed_notification' => 'Failed to import ZIP file.',
|
||||
'import_perms_books' => 'You are lacking the required permissions to create books.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect',
|
||||
'api_user_no_api_permission' => 'The owner of the used API token does not have permission to make API calls',
|
||||
'api_user_token_expired' => 'The authorization token used has expired',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Error thrown when sending a test email:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'The file could not be uploaded. The server may not accept files of this size.',
|
||||
|
||||
'zip_file' => 'The :attribute needs to reference a file within the ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Could not read ZIP file.',
|
||||
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.',
|
||||
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Import ZIP failed to validate with errors:',
|
||||
'import_zip_failed_notification' => 'Failed to import ZIP file.',
|
||||
'import_perms_books' => 'You are lacking the required permissions to create books.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Tajni ključ naveden za dati korišteni API token nije tačan',
|
||||
'api_user_no_api_permission' => 'Vlasnik korištenog API tokena nema dozvolu za upućivanje API poziva',
|
||||
'api_user_token_expired' => 'Autorizacijski token je istekao',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Došlo je do greške prilikom slanja testnog e-maila:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Fajl nije učitan. Server ne prihvata fajlove ove veličine.',
|
||||
|
||||
'zip_file' => 'The :attribute needs to reference a file within the ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'No es pot llegir el fitxer ZIP.',
|
||||
'import_zip_cant_decode_data' => 'No s\'ha pogut trobar i descodificar el fitxer data.json en el fitxer ZIP.',
|
||||
'import_zip_no_data' => 'Les dades del fitxer ZIP no contenen cap llibre, capítol o contingut de pàgina.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Error en validar la importació del ZIP amb els errors:',
|
||||
'import_zip_failed_notification' => 'Error en importar l\'arxiu ZIP.',
|
||||
'import_perms_books' => 'Li falten els permisos necessaris per crear llibres.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'El secret proporcionat per al testimoni d’API utilitzat no és correcte.',
|
||||
'api_user_no_api_permission' => 'El propietari del testimoni API utilitzat no té permís per a fer crides a l’API.',
|
||||
'api_user_token_expired' => 'El testimoni d’autorització utilitzat ha caducat.',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'S’ha produït un error en enviar el correu electrònic de prova:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'No s’ha pogut pujar el fitxer. És possible que el servidor no admeti fitxers d’aquesta mida.',
|
||||
|
||||
'zip_file' => 'El :attribute necessita fer referència a un arxiu dins del ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'El :attribute necessita fer referència a un arxiu de tipus :validTyes, trobat :foundType.',
|
||||
'zip_model_expected' => 'S\'esperava un objecte de dades, però s\'ha trobat ":type".',
|
||||
'zip_unique' => 'El :attribute ha de ser únic pel tipus d\'objecte dins del ZIP.',
|
||||
|
||||
@@ -63,10 +63,10 @@ return [
|
||||
'import_delete_desc' => 'Potvrzením odstraníte nahraný ZIP soubor. Tento krok nelze vrátit zpět.',
|
||||
'import_errors' => 'Chyby importu',
|
||||
'import_errors_desc' => 'Při pokusu o import došlo k následujícím chybám:',
|
||||
'breadcrumb_siblings_for_page' => 'Navigate siblings for page',
|
||||
'breadcrumb_siblings_for_chapter' => 'Navigate siblings for chapter',
|
||||
'breadcrumb_siblings_for_book' => 'Navigate siblings for book',
|
||||
'breadcrumb_siblings_for_bookshelf' => 'Navigate siblings for shelf',
|
||||
'breadcrumb_siblings_for_page' => 'Přejít na jinou stránku',
|
||||
'breadcrumb_siblings_for_chapter' => 'Přejít na jinou kapitolu',
|
||||
'breadcrumb_siblings_for_book' => 'Přejít na jinou knihu',
|
||||
'breadcrumb_siblings_for_bookshelf' => 'Přejít na jinou polici',
|
||||
|
||||
// Permissions and restrictions
|
||||
'permissions' => 'Oprávnění',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Nelze načíst ZIP soubor.',
|
||||
'import_zip_cant_decode_data' => 'Nelze najít a dekódovat data.json v archivu ZIP.',
|
||||
'import_zip_no_data' => 'ZIP archiv neobsahuje knihy, kapitoly nebo stránky.',
|
||||
'import_zip_data_too_large' => 'Obsah souboru data.json v archivu ZIP překračuje maximální povolenou velikost.',
|
||||
'import_validation_failed' => 'Importování ZIP selhalo s chybami:',
|
||||
'import_zip_failed_notification' => 'Nepodařilo se naimportovat ZIP soubor.',
|
||||
'import_perms_books' => 'Chybí vám požadovaná oprávnění k vytvoření knih.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Poskytnutý Token Secret neodpovídá použitému API tokenu',
|
||||
'api_user_no_api_permission' => 'Vlastník použitého API tokenu nemá oprávnění provádět API volání',
|
||||
'api_user_token_expired' => 'Platnost autorizačního tokenu vypršela',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Při posílání testovacího e-mailu nastala chyba:',
|
||||
|
||||
@@ -11,8 +11,8 @@ return [
|
||||
'updated_page_subject' => 'Aktualizovaná stránka: :pageName',
|
||||
'updated_page_intro' => 'V :appName byla aktualizována stránka:',
|
||||
'updated_page_debounce' => 'Po nějakou dobu neobdržíte další oznámení o aktualizaci této stránky stejným editorem, aby se omezil počet stejných zpráv.',
|
||||
'comment_mention_subject' => 'You have been mentioned in a comment on page: :pageName',
|
||||
'comment_mention_intro' => 'You were mentioned in a comment on :appName:',
|
||||
'comment_mention_subject' => 'Byli jste zmíněni v komentáři na stránce: :pageName',
|
||||
'comment_mention_intro' => 'Byli jste zmíněni v komentáři na webu :appName:',
|
||||
|
||||
'detail_page_name' => 'Název stránky:',
|
||||
'detail_page_path' => 'Umístění:',
|
||||
|
||||
@@ -23,7 +23,7 @@ return [
|
||||
'notifications_desc' => 'Nastavte si e-mailová oznámení, která dostanete při provedení určitých akcí v systému.',
|
||||
'notifications_opt_own_page_changes' => 'Upozornit na změny stránek u kterých jsem vlastníkem',
|
||||
'notifications_opt_own_page_comments' => 'Upozornit na komentáře na stránkách, které vlastním',
|
||||
'notifications_opt_comment_mentions' => 'Notify when I\'m mentioned in a comment',
|
||||
'notifications_opt_comment_mentions' => 'Upozornit, když mě někdo zmíní v komentáři',
|
||||
'notifications_opt_comment_replies' => 'Upozornit na odpovědi na mé komentáře',
|
||||
'notifications_save' => 'Uložit nastavení',
|
||||
'notifications_update_success' => 'Nastavení oznámení byla aktualizována!',
|
||||
|
||||
@@ -75,8 +75,8 @@ return [
|
||||
'reg_confirm_restrict_domain_placeholder' => 'Žádná omezení nebyla nastavena',
|
||||
|
||||
// Sorting Settings
|
||||
'sorting' => 'Lists & Sorting',
|
||||
'sorting_book_default' => 'Default Book Sort Rule',
|
||||
'sorting' => 'Seznamy a řazení',
|
||||
'sorting_book_default' => 'Výchozí řazení knih',
|
||||
'sorting_book_default_desc' => 'Vybere výchozí pravidlo řazení pro nové knihy. Řazení neovlivní existující knihy a může být upraveno u konkrétní knihy.',
|
||||
'sorting_rules' => 'Pravidla řazení',
|
||||
'sorting_rules_desc' => 'Toto jsou předem definovaná pravidla řazení, která mohou být použita na webu.',
|
||||
@@ -103,8 +103,8 @@ return [
|
||||
'sort_rule_op_updated_date' => 'Datum aktualizace',
|
||||
'sort_rule_op_chapters_first' => 'Kapitoly jako první',
|
||||
'sort_rule_op_chapters_last' => 'Kapitoly jako poslední',
|
||||
'sorting_page_limits' => 'Per-Page Display Limits',
|
||||
'sorting_page_limits_desc' => 'Set how many items to show per-page in various lists within the system. Typically a lower amount will be more performant, while a higher amount avoids the need to click through multiple pages. Using an even multiple of 3 (18, 24, 30, etc...) is recommended.',
|
||||
'sorting_page_limits' => 'Počet zobrazených položek na stránce',
|
||||
'sorting_page_limits_desc' => 'Nastavte, kolik položek se má zobrazit na stránce v různých seznamech na webu. Obvykle bude nižší počet výkonnější, zatímco vyšší počet eliminuje nutnost proklikávat se několika stránkami. Doporučuje se použít sudý násobek čísla 3 (18, 24, 30 atd.).',
|
||||
|
||||
// Maintenance settings
|
||||
'maint' => 'Údržba',
|
||||
@@ -197,13 +197,13 @@ return [
|
||||
'role_import_content' => 'Importovat obsah',
|
||||
'role_editor_change' => 'Změnit editor stránek',
|
||||
'role_notifications' => 'Přijímat a spravovat oznámení',
|
||||
'role_permission_note_users_and_roles' => 'These permissions will technically also provide visibility & searching of users & roles in the system.',
|
||||
'role_permission_note_users_and_roles' => 'Tato oprávnění zároveň umožní zobrazit a vyhledat uživatele a role na webu.',
|
||||
'role_asset' => 'Obsahová oprávnění',
|
||||
'roles_system_warning' => 'Berte na vědomí, že přístup k některému ze tří výše uvedených oprávnění může uživateli umožnit změnit svá vlastní oprávnění nebo oprávnění ostatních uživatelů v systému. Přiřazujte role s těmito oprávněními pouze důvěryhodným uživatelům.',
|
||||
'role_asset_desc' => 'Tato oprávnění řídí přístup k obsahu napříč systémem. Specifická oprávnění na knihách, kapitolách a stránkách převáží tato nastavení.',
|
||||
'role_asset_admins' => 'Administrátoři automaticky dostávají přístup k veškerému obsahu, ale tyto volby mohou ukázat nebo skrýt volby v uživatelském rozhraní.',
|
||||
'role_asset_image_view_note' => 'To se týká viditelnosti ve správci obrázků. Skutečný přístup k nahraným souborům obrázků bude záviset na možnosti uložení systémových obrázků.',
|
||||
'role_asset_users_note' => 'These permissions will technically also provide visibility & searching of users in the system.',
|
||||
'role_asset_users_note' => 'Tato oprávnění zároveň umožní zobrazit a vyhledat uživatele v systému.',
|
||||
'role_all' => 'Vše',
|
||||
'role_own' => 'Vlastní',
|
||||
'role_controlled_by_asset' => 'Řídí se obsahem, do kterého jsou nahrávány',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Nahrávání :attribute se nezdařilo.',
|
||||
|
||||
'zip_file' => ':attribute musí odkazovat na soubor v archivu ZIP.',
|
||||
'zip_file_size' => 'Soubor :attribute nesmí překročit :size MB.',
|
||||
'zip_file_mime' => ':attribute musí odkazovat na soubor typu :validTypes, nalezen :foundType.',
|
||||
'zip_model_expected' => 'Očekáván datový objekt, ale nalezen „:type“.',
|
||||
'zip_unique' => ':attribute musí být jedinečný pro typ objektu v archivu ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Wedi methu darllen ffeil ZIP.',
|
||||
'import_zip_cant_decode_data' => 'Wedi methu ffeindio a dadgodio cynnwys ZIP data.json.',
|
||||
'import_zip_no_data' => 'Nid oes cynnwys llyfr, pennod neu dudalen disgwyliedig yn nata ffeil ZIP.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'ZIP mewnforyn wedi\'i methu dilysu gyda gwallau:',
|
||||
'import_zip_failed_notification' => 'Wedi methu mewnforio ffeil ZIP.',
|
||||
'import_perms_books' => 'Dych chi\'n methu\'r caniatâd gofynnol i greu llyfrau.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Mae\'r gyfrinach a ddarparwyd ar gyfer y tocyn API defnyddiedig a roddwyd yn anghywir',
|
||||
'api_user_no_api_permission' => 'Nid oes gan berchennog y tocyn API a ddefnyddiwyd ganiatâd i wneud galwadau API',
|
||||
'api_user_token_expired' => 'Mae\'r tocyn awdurdodi a ddefnyddiwyd wedi dod i ben',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Gwall a daflwyd wrth anfon e-bost prawf:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Nid oedd modd uwchlwytho’r ffeil. Efallai na fydd y gweinydd yn derbyn ffeiliau o\'r maint hwn.',
|
||||
|
||||
'zip_file' => 'Mae\'r :attribute angen cyfeirio at ffeil yn y ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'Mae\'r :attribute angen cyfeirio at ffeil o fath :valid Types, sydd wedi\'i ffeindio :foundType.',
|
||||
'zip_model_expected' => 'Dyswgyl am wrthrych data ond wedi ffeindio ":type".',
|
||||
'zip_unique' => 'Mae rhaid y :attribute fod yn unigol i\'r fath o wrthrych yn y ZIP.',
|
||||
|
||||
@@ -48,7 +48,7 @@ return [
|
||||
'superscript' => 'Hævet',
|
||||
'subscript' => 'Sænket',
|
||||
'text_color' => 'Tekstfarve',
|
||||
'highlight_color' => 'Highlight color',
|
||||
'highlight_color' => 'Fremhævelsesfarve',
|
||||
'custom_color' => 'Tilpasset farve',
|
||||
'remove_color' => 'Fjern farve',
|
||||
'background_color' => 'Baggrundsfarve',
|
||||
|
||||
@@ -252,7 +252,7 @@ return [
|
||||
'pages_edit_switch_to_markdown_stable' => '(Stabilt indhold)',
|
||||
'pages_edit_switch_to_wysiwyg' => 'Skift til WYSIWYG redigering',
|
||||
'pages_edit_switch_to_new_wysiwyg' => 'Skift til ny WYSIWYG (Hvad man ser, er hvad man får)',
|
||||
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)',
|
||||
'pages_edit_switch_to_new_wysiwyg_desc' => '(I Beta Test)',
|
||||
'pages_edit_set_changelog' => 'Sæt ændringsoversigt',
|
||||
'pages_edit_enter_changelog_desc' => 'Indtast en kort beskrivelse af ændringer du har lavet',
|
||||
'pages_edit_enter_changelog' => 'Indtast ændringsoversigt',
|
||||
@@ -397,11 +397,11 @@ return [
|
||||
'comment' => 'Kommentar',
|
||||
'comments' => 'Kommentarer',
|
||||
'comment_add' => 'Tilføj kommentar',
|
||||
'comment_none' => 'No comments to display',
|
||||
'comment_none' => 'Ingen kommentarer at vise',
|
||||
'comment_placeholder' => 'Skriv en kommentar her',
|
||||
'comment_thread_count' => ':count Comment Thread|:count Comment Threads',
|
||||
'comment_thread_count' => ':count Kommentar Tråde:count Kommentar Tråde',
|
||||
'comment_archived_count' => ':count Arkiveret',
|
||||
'comment_archived_threads' => 'Archived Threads',
|
||||
'comment_archived_threads' => 'Arkiverede Tråde',
|
||||
'comment_save' => 'Gem kommentar',
|
||||
'comment_new' => 'Ny kommentar',
|
||||
'comment_created' => 'kommenteret :createDiff',
|
||||
@@ -410,8 +410,8 @@ return [
|
||||
'comment_deleted_success' => 'Kommentar slettet',
|
||||
'comment_created_success' => 'Kommentaren er tilføjet',
|
||||
'comment_updated_success' => 'Kommentaren er opdateret',
|
||||
'comment_archive_success' => 'Comment archived',
|
||||
'comment_unarchive_success' => 'Comment un-archived',
|
||||
'comment_archive_success' => 'Kommentar arkiveret',
|
||||
'comment_unarchive_success' => 'Kommentaren er ikke længere arkiveret',
|
||||
'comment_view' => 'Se kommentar',
|
||||
'comment_jump_to_thread' => 'Hop til tråd',
|
||||
'comment_delete_confirm' => 'Er du sikker på, at du vil slette denne kommentar?',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Kunne ikke læse ZIP-filen.',
|
||||
'import_zip_cant_decode_data' => 'Kunne ikke finde og afkode ZIP data.json-indhold.',
|
||||
'import_zip_no_data' => 'ZIP-filens data har ikke noget forventet bog-, kapitel- eller sideindhold.',
|
||||
'import_zip_data_too_large' => 'Indholdet af ZIP data.json overstiger den konfigurerede maksimale uploadstørrelse for applikationen.',
|
||||
'import_validation_failed' => 'Import ZIP kunne ikke valideres med fejl:',
|
||||
'import_zip_failed_notification' => 'Kunne ikke importere ZIP-fil.',
|
||||
'import_perms_books' => 'Du mangler de nødvendige tilladelser til at oprette bøger.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Hemmeligheden leveret til det givne anvendte API-token er forkert',
|
||||
'api_user_no_api_permission' => 'Ejeren af den brugte API token har ikke adgang til at foretage API-kald',
|
||||
'api_user_token_expired' => 'Den brugte godkendelsestoken er udløbet',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Følgende fejl opstod under afsendelse af testemail:',
|
||||
|
||||
@@ -11,8 +11,8 @@ return [
|
||||
'updated_page_subject' => 'Opdateret side: :pageName',
|
||||
'updated_page_intro' => 'En side er blevet opdateret i :appName:',
|
||||
'updated_page_debounce' => 'For at forhindre en masse af notifikationer, i et stykke tid vil du ikke blive sendt notifikationer for yderligere redigeringer til denne side af den samme editor.',
|
||||
'comment_mention_subject' => 'You have been mentioned in a comment on page: :pageName',
|
||||
'comment_mention_intro' => 'You were mentioned in a comment on :appName:',
|
||||
'comment_mention_subject' => 'Du er blevet nævnt i en kommentar på siden: :pageName',
|
||||
'comment_mention_intro' => 'Du blev nævnt i en kommentar på :appName:',
|
||||
|
||||
'detail_page_name' => 'Sidens navn:',
|
||||
'detail_page_path' => 'Sidesti:',
|
||||
|
||||
@@ -23,7 +23,7 @@ return [
|
||||
'notifications_desc' => 'Administrer de e-mail-notifikationer, du modtager, når visse aktiviteter udføres i systemet.',
|
||||
'notifications_opt_own_page_changes' => 'Adviser ved ændringer af sider, jeg ejer',
|
||||
'notifications_opt_own_page_comments' => 'Adviser ved kommentarer på sider, jeg ejer',
|
||||
'notifications_opt_comment_mentions' => 'Notify when I\'m mentioned in a comment',
|
||||
'notifications_opt_comment_mentions' => 'Giv besked, når jeg er nævnt i en kommentar',
|
||||
'notifications_opt_comment_replies' => 'Adviser ved svar på mine kommentarer',
|
||||
'notifications_save' => 'Gem indstillinger',
|
||||
'notifications_update_success' => 'Indstillinger for notifikationer er blevet opdateret!',
|
||||
|
||||
@@ -75,8 +75,8 @@ return [
|
||||
'reg_confirm_restrict_domain_placeholder' => 'Ingen restriktion opsat',
|
||||
|
||||
// Sorting Settings
|
||||
'sorting' => 'Lists & Sorting',
|
||||
'sorting_book_default' => 'Default Book Sort Rule',
|
||||
'sorting' => 'Lister & Sortering',
|
||||
'sorting_book_default' => 'Standardregel for sortering af bog',
|
||||
'sorting_book_default_desc' => 'Vælg den standardsorteringsregel, der skal gælde for nye bøger. Dette påvirker ikke eksisterende bøger og kan tilsidesættes for hver enkelt bog.',
|
||||
'sorting_rules' => 'Regler for sortering',
|
||||
'sorting_rules_desc' => 'Det er foruddefinerede sorteringsoperationer, som kan anvendes på indhold i systemet.',
|
||||
@@ -103,8 +103,8 @@ return [
|
||||
'sort_rule_op_updated_date' => 'Opdateret dato',
|
||||
'sort_rule_op_chapters_first' => 'Kapitler først',
|
||||
'sort_rule_op_chapters_last' => 'De sidste kapitler',
|
||||
'sorting_page_limits' => 'Per-Page Display Limits',
|
||||
'sorting_page_limits_desc' => 'Set how many items to show per-page in various lists within the system. Typically a lower amount will be more performant, while a higher amount avoids the need to click through multiple pages. Using an even multiple of 3 (18, 24, 30, etc...) is recommended.',
|
||||
'sorting_page_limits' => 'Visningsgrænser pr. side',
|
||||
'sorting_page_limits_desc' => 'Angiv, hvor mange elementer der skal vises pr. side i forskellige lister i systemet. Typisk vil et lavere beløb være mere effektivt, mens et højere beløb undgår behovet for at klikke sig igennem flere sider. Det anbefales at bruge et lige multiplum af 3 (18, 24, 30 osv.).',
|
||||
|
||||
// Maintenance settings
|
||||
'maint' => 'Vedligeholdelse',
|
||||
@@ -197,13 +197,13 @@ return [
|
||||
'role_import_content' => 'Importer indhold',
|
||||
'role_editor_change' => 'Skift side editor',
|
||||
'role_notifications' => 'Modtag og administrer notifikationer',
|
||||
'role_permission_note_users_and_roles' => 'These permissions will technically also provide visibility & searching of users & roles in the system.',
|
||||
'role_permission_note_users_and_roles' => 'Disse tilladelser vil teknisk set også give synlighed og søgning efter brugere og roller i systemet.',
|
||||
'role_asset' => 'Tilladelser for medier og "assets"',
|
||||
'roles_system_warning' => 'Vær opmærksom på, at adgang til alle af de ovennævnte tre tilladelser, kan give en bruger mulighed for at ændre deres egne brugerrettigheder eller brugerrettigheder for andre i systemet. Tildel kun roller med disse tilladelser til betroede brugere.',
|
||||
'role_asset_desc' => 'Disse tilladelser kontrollerer standardadgang til medier og "assets" i systemet. Tilladelser til bøger, kapitler og sider tilsidesætter disse tilladelser.',
|
||||
'role_asset_admins' => 'Administratorer får automatisk adgang til alt indhold, men disse indstillinger kan vise eller skjule UI-indstillinger.',
|
||||
'role_asset_image_view_note' => 'Dette vedrører synlighed i billedhåndteringen. Den faktiske adgang til uploadede billedfiler vil afhænge af systemets billedlagringsindstilling.',
|
||||
'role_asset_users_note' => 'These permissions will technically also provide visibility & searching of users in the system.',
|
||||
'role_asset_users_note' => 'Disse tilladelser vil teknisk set også give synlighed og søgning efter brugere i systemet.',
|
||||
'role_all' => 'Alle',
|
||||
'role_own' => 'Eget',
|
||||
'role_controlled_by_asset' => 'Styres af det medie/"asset", de uploades til',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Filen kunne ikke oploades. Serveren accepterer muligvis ikke filer af denne størrelse.',
|
||||
|
||||
'zip_file' => 'Attributten skal henvise til en fil i ZIP.',
|
||||
'zip_file_size' => 'Filen :attribute må ikke overstige: størrelse MB.',
|
||||
'zip_file_mime' => 'Attributten skal henvise til en fil af typen: validTypes, fundet:foundType.',
|
||||
'zip_model_expected' => 'Data objekt forventet men ":type" fundet.',
|
||||
'zip_unique' => 'Attributten skal være unik for objekttypen i ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'ZIP-Datei konnte nicht gelesen werden.',
|
||||
'import_zip_cant_decode_data' => 'ZIP data.json konnte nicht gefunden und dekodiert werden.',
|
||||
'import_zip_no_data' => 'ZIP-Datei Daten haben kein erwartetes Buch, Kapitel oder Seiteninhalt.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'ZIP Import konnte mit Fehlern nicht validiert werden:',
|
||||
'import_zip_failed_notification' => 'Importieren der ZIP-Datei fehlgeschlagen.',
|
||||
'import_perms_books' => 'Ihnen fehlt die erforderliche Berechtigung, um Bücher zu erstellen.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Das Kennwort für das angegebene API-Token ist falsch',
|
||||
'api_user_no_api_permission' => 'Der Besitzer des verwendeten API-Tokens hat keine Berechtigung für API-Aufrufe',
|
||||
'api_user_token_expired' => 'Das verwendete Autorisierungstoken ist abgelaufen',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Fehler beim Versenden einer Test E-Mail:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Die Datei konnte nicht hochgeladen werden. Der Server akzeptiert möglicherweise keine Dateien dieser Größe.',
|
||||
|
||||
'zip_file' => ':attribute muss eine Datei innerhalb des ZIP referenzieren.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => ':attribute muss eine Datei des Typs :validType referenzieren, gefunden :foundType.',
|
||||
'zip_model_expected' => 'Datenobjekt erwartet, aber ":type" gefunden.',
|
||||
'zip_unique' => ':attribute muss für den Objekttyp innerhalb des ZIP eindeutig sein.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'ZIP-Datei konnte nicht gelesen werden.',
|
||||
'import_zip_cant_decode_data' => 'Konnte Inhalt der data.json im ZIP nicht finden und dekodieren.',
|
||||
'import_zip_no_data' => 'ZIP-Datei hat kein erwartetes Buch, Kapitel oder Seiteninhalt.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'ZIP Import konnte aufgrund folgender Fehler nicht validiert werden:',
|
||||
'import_zip_failed_notification' => 'Importieren der ZIP-Datei fehlgeschlagen.',
|
||||
'import_perms_books' => 'Dir fehlt die erforderliche Berechtigung, um Bücher zu erstellen.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Das für den API-Token angegebene geheime Token ist falsch',
|
||||
'api_user_no_api_permission' => 'Der Besitzer des verwendeten API-Token hat keine Berechtigung für API-Aufrufe',
|
||||
'api_user_token_expired' => 'Das verwendete Autorisierungs-Token ist abgelaufen',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Fehler beim Senden einer Test E-Mail:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Die Datei konnte nicht hochgeladen werden. Der Server akzeptiert möglicherweise keine Dateien dieser Größe.',
|
||||
|
||||
'zip_file' => ':attribute muss auf eine Datei innerhalb des ZIP verweisen.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => ':attribute muss eine Datei des Typs :validType referenzieren, gefunden :foundType.',
|
||||
'zip_model_expected' => 'Datenobjekt erwartet, aber ":type" gefunden.',
|
||||
'zip_unique' => ':attribute muss für den Objekttyp innerhalb des ZIP eindeutig sein.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Could not read ZIP file.',
|
||||
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.',
|
||||
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Import ZIP failed to validate with errors:',
|
||||
'import_zip_failed_notification' => 'Failed to import ZIP file.',
|
||||
'import_perms_books' => 'You are lacking the required permissions to create books.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Το μυστικό που παρέχεται για το δεδομένο χρησιμοποιημένο διακριτικό API είναι εσφαλμένο',
|
||||
'api_user_no_api_permission' => 'Ο ιδιοκτήτης του χρησιμοποιημένου διακριτικού API δεν έχει άδεια για να κάνει κλήσεις API',
|
||||
'api_user_token_expired' => 'Το διακριτικό εξουσιοδότησης που χρησιμοποιείται έχει λήξει',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Σφάλμα κατά την αποστολή δοκιμαστικού email:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Δεν ήταν δυνατή η αποστολή του αρχείου. Ο διακομιστής ενδέχεται να μην δέχεται αρχεία αυτού του μεγέθους.',
|
||||
|
||||
'zip_file' => 'Το :attribute πρέπει να παραπέμπει σε ένα αρχείο εντός του ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'Το :attribute πρέπει να αναφέρεται σε αρχείο τύπου :validTypes, βρέθηκε :foundType.',
|
||||
'zip_model_expected' => 'Αναμενόταν αντικείμενο δεδομένων, αλλά ":type" βρέθηκε.',
|
||||
'zip_unique' => 'Το :attribute πρέπει να είναι μοναδικό για τον τύπο αντικειμένου εντός του ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Could not read ZIP file.',
|
||||
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.',
|
||||
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Import ZIP failed to validate with errors:',
|
||||
'import_zip_failed_notification' => 'Failed to import ZIP file.',
|
||||
'import_perms_books' => 'You are lacking the required permissions to create books.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect',
|
||||
'api_user_no_api_permission' => 'The owner of the used API token does not have permission to make API calls',
|
||||
'api_user_token_expired' => 'The authorization token used has expired',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Error thrown when sending a test email:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'The file could not be uploaded. The server may not accept files of this size.',
|
||||
|
||||
'zip_file' => 'The :attribute needs to reference a file within the ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'No se pudo leer el archivo ZIP.',
|
||||
'import_zip_cant_decode_data' => 'No se pudo encontrar y decodificar el archivo data.json. en el archivo ZIP.',
|
||||
'import_zip_no_data' => 'Los datos del archivo ZIP no contienen ningún libro, capítulo o contenido de página.',
|
||||
'import_zip_data_too_large' => 'El contenido del ZIP data.json excede el tamaño máximo de carga configurado.',
|
||||
'import_validation_failed' => 'Error al validar la importación del ZIP con errores:',
|
||||
'import_zip_failed_notification' => 'Error al importar archivo ZIP.',
|
||||
'import_perms_books' => 'Le faltan los permisos necesarios para crear libros.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'El secreto proporcionado para el token API usado es incorrecto',
|
||||
'api_user_no_api_permission' => 'El propietario del token API usado no tiene permiso para hacer llamadas API',
|
||||
'api_user_token_expired' => 'El token de autorización usado ha caducado',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Error al enviar un email de prueba:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'El archivo no ha podido subirse. Es posible que el servidor no acepte archivos de este tamaño.',
|
||||
|
||||
'zip_file' => 'El :attribute necesita hacer referencia a un archivo dentro del ZIP.',
|
||||
'zip_file_size' => 'El archivo :attribute no debe exceder :size MB.',
|
||||
'zip_file_mime' => 'El :attribute necesita hacer referencia a un archivo de tipo :validTypes, encontrado :foundType.',
|
||||
'zip_model_expected' => 'Se esperaba un objeto de datos, pero se encontró ":type".',
|
||||
'zip_unique' => 'El :attribute debe ser único para el tipo de objeto dentro del ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'No se pudo leer el archivo ZIP.',
|
||||
'import_zip_cant_decode_data' => 'No se pudo encontrar ni decodificar el contenido del archivo ZIP data.json.',
|
||||
'import_zip_no_data' => 'Los datos del archivo ZIP no tienen un libro, un capítulo o contenido de página en su contenido.',
|
||||
'import_zip_data_too_large' => 'El contenido del ZIP data.json excede el tamaño máximo de carga configurado.',
|
||||
'import_validation_failed' => 'Error al validar la importación del ZIP con los errores:',
|
||||
'import_zip_failed_notification' => 'Error al importar archivo ZIP.',
|
||||
'import_perms_books' => 'Le faltan los permisos necesarios para crear libros.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'El secreto proporcionado para el token API usado es incorrecto',
|
||||
'api_user_no_api_permission' => 'El propietario del token API usado no tiene permiso para hacer llamadas API',
|
||||
'api_user_token_expired' => 'El token de autorización usado ha caducado',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Error al enviar un email de prueba:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'El archivo no se pudo subir. Puede ser que el servidor no acepte archivos de este tamaño.',
|
||||
|
||||
'zip_file' => 'El :attribute necesita hacer referencia a un archivo dentro del ZIP.',
|
||||
'zip_file_size' => 'El archivo :attribute no debe exceder :size MB.',
|
||||
'zip_file_mime' => 'El :attribute necesita hacer referencia a un archivo de tipo :validTypes, encontrado :foundType.',
|
||||
'zip_model_expected' => 'Se esperaba un objeto de datos, pero se encontró ":type".',
|
||||
'zip_unique' => 'El :attribute debe ser único para el tipo de objeto dentro del ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'ZIP-faili lugemine ebaõnnestus.',
|
||||
'import_zip_cant_decode_data' => 'ZIP-failist ei leitud data.json sisu.',
|
||||
'import_zip_no_data' => 'ZIP-failist ei leitud raamatute, peatükkide või lehtede sisu.',
|
||||
'import_zip_data_too_large' => 'ZIP-faili data.json sisu ületab rakenduses seadistatud maksimaalse failisuuruse.',
|
||||
'import_validation_failed' => 'Imporditud ZIP-faili valideerimine ebaõnnestus vigadega:',
|
||||
'import_zip_failed_notification' => 'ZIP-faili importimine ebaõnnestus.',
|
||||
'import_perms_books' => 'Sul puuduvad õigused raamatute lisamiseks.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'API tunnusele lisatud salajane võti ei ole korrektne',
|
||||
'api_user_no_api_permission' => 'Selle API tunnuse omanikul ei ole õigust API päringuid teha',
|
||||
'api_user_token_expired' => 'Volitustunnus on aegunud',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Test e-kirja saatmisel tekkis viga:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Faili üleslaadimine ebaõnnestus. Server ei pruugi sellise suurusega faile vastu võtta.',
|
||||
|
||||
'zip_file' => ':attribute peab viitama failile ZIP-arhiivi sees.',
|
||||
'zip_file_size' => 'Fail :attribute ei tohi olla suurem kui :size MB.',
|
||||
'zip_file_mime' => ':attribute peab viitama :validTypes tüüpi failile, leiti :foundType.',
|
||||
'zip_model_expected' => 'Oodatud andmete asemel leiti ":type".',
|
||||
'zip_unique' => ':attribute peab olema ZIP-arhiivi piires objekti tüübile unikaalne.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Could not read ZIP file.',
|
||||
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.',
|
||||
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Import ZIP failed to validate with errors:',
|
||||
'import_zip_failed_notification' => 'Failed to import ZIP file.',
|
||||
'import_perms_books' => 'You are lacking the required permissions to create books.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect',
|
||||
'api_user_no_api_permission' => 'The owner of the used API token does not have permission to make API calls',
|
||||
'api_user_token_expired' => 'The authorization token used has expired',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Error thrown when sending a test email:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'The file could not be uploaded. The server may not accept files of this size.',
|
||||
|
||||
'zip_file' => 'The :attribute needs to reference a file within the ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'امکان ایجاد کاربر وجود ندارد؛ زیرا ارسال ایمیل دعوت با خطا مواجه شد.',
|
||||
'import_zip_cant_decode_data' => 'محتوای data.json در فایل ZIP پیدا یا رمزگشایی نشد.',
|
||||
'import_zip_no_data' => 'دادههای فایل ZIP فاقد محتوای کتاب، فصل یا صفحه مورد انتظار است.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'اعتبارسنجی فایل ZIP واردشده با خطا مواجه شد:',
|
||||
'import_zip_failed_notification' => ' فایل ZIP وارد نشد.',
|
||||
'import_perms_books' => 'شما مجوز لازم برای ایجاد کتاب را ندارید.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'راز ارائه شده برای کد API استفاده شده نادرست است',
|
||||
'api_user_no_api_permission' => 'مالک نشانه API استفاده شده اجازه برقراری تماس های API را ندارد',
|
||||
'api_user_token_expired' => 'رمز مجوز استفاده شده منقضی شده است',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'خطا در هنگام ارسال ایمیل آزمایشی:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'بارگذاری فایل :attribute موفقیت آمیز نبود.',
|
||||
|
||||
'zip_file' => 'ویژگی :attribute باید به یک فایل درون پرونده فشرده شده اشاره کند.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'ویژگی :attribute باید به فایلی با نوع :validTypes اشاره کند، اما نوع یافتشده :foundType است.',
|
||||
'zip_model_expected' => 'سیستم در این بخش انتظار دریافت یک شیء دادهای را داشت، اما «:type» دریافت گردید',
|
||||
'zip_unique' => 'برای هر نوع شیء در فایل ZIP، مقدار ویژگی :attribute باید یکتا و بدون تکرار باشد.',
|
||||
|
||||
@@ -110,6 +110,7 @@ Sovellus ei tunnista ulkoisen todennuspalvelun pyyntöä. Ongelman voi aiheuttaa
|
||||
'import_zip_cant_read' => 'ZIP-tiedostoa ei voitu lukea.',
|
||||
'import_zip_cant_decode_data' => 'ZIP-tiedoston data.json sisältöä ei löydy eikä sitä voitu purkaa.',
|
||||
'import_zip_no_data' => 'ZIP-tiedostoilla ei ole odotettua kirjaa, lukua tai sivun sisältöä.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Tuonti ZIP epäonnistui virheiden kanssa:',
|
||||
'import_zip_failed_notification' => 'ZIP-tiedoston tuominen epäonnistui.',
|
||||
'import_perms_books' => 'Sinulla ei ole tarvittavia oikeuksia luoda kirjoja.',
|
||||
@@ -125,6 +126,7 @@ Sovellus ei tunnista ulkoisen todennuspalvelun pyyntöä. Ongelman voi aiheuttaa
|
||||
'api_incorrect_token_secret' => 'API-tunnisteelle annettu salainen avain on virheellinen',
|
||||
'api_user_no_api_permission' => 'Käytetyn API-tunnisteen omistajalla ei ole oikeutta tehdä API-kutsuja',
|
||||
'api_user_token_expired' => 'Käytetty valtuutuskoodi on vanhentunut',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Virhe testisähköpostia lähetettäessä:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Tiedostoa ei voitu ladata. Palvelin ei ehkä hyväksy tämän kokoisia tiedostoja.',
|
||||
|
||||
'zip_file' => 'Attribuutin :attribute on viitattava tiedostoon ZIP-tiedoston sisällä.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
|
||||
@@ -54,7 +54,7 @@ return [
|
||||
'import_continue_desc' => 'Examinez le contenu à importer à partir du fichier ZIP téléchargé. Lorsque vous êtes prêt, lancez l\'importation pour ajouter son contenu à ce système. Le fichier d\'importation ZIP téléchargé sera automatiquement supprimé si l\'importation est réussie.',
|
||||
'import_details' => 'Détails de l\'importation',
|
||||
'import_run' => 'Exécuter Importation',
|
||||
'import_size' => ':size taille du ZIP d\'import',
|
||||
'import_size' => ':size Taille du fichier ZIP à importer',
|
||||
'import_uploaded_at' => ':relativeTime téléchargé',
|
||||
'import_uploaded_by' => 'Téléchargé par',
|
||||
'import_location' => 'Emplacement de l\'importation',
|
||||
@@ -330,13 +330,13 @@ return [
|
||||
|
||||
// Editor Sidebar
|
||||
'toggle_sidebar' => 'Afficher/masquer la barre latérale',
|
||||
'page_tags' => 'Mots-clés de la page',
|
||||
'chapter_tags' => 'Mots-clés du chapitre',
|
||||
'book_tags' => 'Mots-clés du livre',
|
||||
'shelf_tags' => 'Mots-clés de l\'étagère',
|
||||
'tag' => 'Mot-clé',
|
||||
'tags' => 'Mots-clés',
|
||||
'tags_index_desc' => 'Les tags peuvent être appliqués au contenu du système pour appliquer une forme flexible de catégorisation. Les tags peuvent avoir à la fois une clé et une valeur, la valeur étant facultative. Une fois appliqué, le contenu peut ensuite être interrogé à l’aide du nom et de la valeur du tag.',
|
||||
'page_tags' => 'Étiquettes de la page',
|
||||
'chapter_tags' => 'Étiquettes du chapitre',
|
||||
'book_tags' => 'Étiquettes du livre',
|
||||
'shelf_tags' => 'Étiquettes de l\'étagère',
|
||||
'tag' => 'Étiquette',
|
||||
'tags' => 'Étiquettes',
|
||||
'tags_index_desc' => 'Les étiquettes peuvent être mises sur le contenu pour appliquer une forme flexible de catégorisation. Les étiquettes peuvent avoir à la fois une clé et une valeur, la valeur étant facultative. Une fois appliqué, le contenu peut ensuite être interrogé à l’aide du nom et de la valeur de l’étiquette.',
|
||||
'tag_name' => 'Nom de l’étiquette',
|
||||
'tag_value' => 'Valeur du mot-clé (optionnel)',
|
||||
'tags_explain' => "Ajouter des mots-clés pour catégoriser votre contenu.",
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Impossible de lire le fichier ZIP.',
|
||||
'import_zip_cant_decode_data' => 'Impossible de trouver et de décoder le contenu ZIP data.json.',
|
||||
'import_zip_no_data' => 'Les données du fichier ZIP n\'ont pas de livre, de chapitre ou de page attendus.',
|
||||
'import_zip_data_too_large' => 'Le contenu du fichier ZIP pour data.json dépasse la taille maximale de téléversement autorisée.',
|
||||
'import_validation_failed' => 'L\'importation du ZIP n\'a pas été validée avec les erreurs :',
|
||||
'import_zip_failed_notification' => 'Impossible d\'importer le fichier ZIP.',
|
||||
'import_perms_books' => 'Vous n\'avez pas les permissions requises pour créer des livres.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Le secret fourni pour le jeton d\'API utilisé est incorrect',
|
||||
'api_user_no_api_permission' => 'Le propriétaire du jeton API utilisé n\'a pas la permission de passer des requêtes API',
|
||||
'api_user_token_expired' => 'Le jeton d\'autorisation utilisé a expiré',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Erreur émise lors de l\'envoi d\'un e-mail de test :',
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
*/
|
||||
return [
|
||||
|
||||
'new_comment_subject' => 'Nouveau commentaire sur la page: :pageName',
|
||||
'new_comment_subject' => 'Nouveau commentaire sur la page : :pageName',
|
||||
'new_comment_intro' => 'Un utilisateur a commenté une page dans :appName:',
|
||||
'new_page_subject' => 'Nouvelle page: :pageName',
|
||||
'new_page_intro' => 'Une nouvelle page a été créée dans :appName:',
|
||||
'updated_page_subject' => 'Page mise à jour: :pageName',
|
||||
'updated_page_intro' => 'Une page a été mise à jour dans :appName:',
|
||||
'updated_page_debounce' => 'Pour éviter de nombreuses notifications, pendant un certain temps, vous ne recevrez pas de notifications pour d\'autres modifications de cette page par le même éditeur.',
|
||||
'comment_mention_subject' => 'You have been mentioned in a comment on page: :pageName',
|
||||
'comment_mention_intro' => 'You were mentioned in a comment on :appName:',
|
||||
'comment_mention_subject' => 'Vous avez été mentionné dans un commentaire sur la page : :pageName',
|
||||
'comment_mention_intro' => 'Vous avez été mentionné dans un commentaire sur :appName:',
|
||||
|
||||
'detail_page_name' => 'Nom de la page :',
|
||||
'detail_page_path' => 'Chemin de la page :',
|
||||
|
||||
@@ -23,7 +23,7 @@ return [
|
||||
'notifications_desc' => 'Contrôlez les notifications par e-mail que vous recevez lorsque certaines activités sont effectuées dans le système.',
|
||||
'notifications_opt_own_page_changes' => 'Notifier lors des modifications des pages que je possède',
|
||||
'notifications_opt_own_page_comments' => 'Notifier lorsque les pages que je possède sont commentées',
|
||||
'notifications_opt_comment_mentions' => 'Notify when I\'m mentioned in a comment',
|
||||
'notifications_opt_comment_mentions' => 'Notifier lorsque je suis mentionné dans un commentaire',
|
||||
'notifications_opt_comment_replies' => 'Notifier les réponses à mes commentaires',
|
||||
'notifications_save' => 'Enregistrer les préférences',
|
||||
'notifications_update_success' => 'Les préférences de notification ont été mises à jour !',
|
||||
|
||||
@@ -17,14 +17,14 @@ return [
|
||||
'app_features_security' => 'Fonctionnalités et sécurité',
|
||||
'app_name' => 'Nom de l\'application',
|
||||
'app_name_desc' => 'Ce nom est affiché dans l\'en-tête et les e-mails.',
|
||||
'app_name_header' => 'Afficher le nom dans l\'en-tête ?',
|
||||
'app_name_header' => 'Afficher le nom dans l\'en-tête',
|
||||
'app_public_access' => 'Accès public',
|
||||
'app_public_access_desc' => 'L\'activation de cette option permettra aux visiteurs, qui ne sont pas connectés, d\'accéder au contenu de votre instance BookStack.',
|
||||
'app_public_access_desc_guest' => 'L\'accès pour les visiteurs publics peut être contrôlé par l\'utilisateur "Guest".',
|
||||
'app_public_access_toggle' => 'Autoriser l\'accès public',
|
||||
'app_public_viewing' => 'Accepter l\'affichage public des pages ?',
|
||||
'app_secure_images' => 'Ajout d\'image sécurisé',
|
||||
'app_secure_images_toggle' => 'Activer l\'ajout d\'image sécurisé',
|
||||
'app_secure_images_toggle' => 'Activer l\'ajout d\'image sécurisée',
|
||||
'app_secure_images_desc' => 'Pour des questions de performances, toutes les images sont publiques. Cette option ajoute une chaîne aléatoire difficile à deviner dans les URLs des images.',
|
||||
'app_default_editor' => 'Éditeur de page par défaut',
|
||||
'app_default_editor_desc' => 'Sélectionnez l\'éditeur qui sera utilisé par défaut lors de l\'édition de nouvelles pages. Cela peut être remplacé au niveau de la page où les permissions sont autorisées.',
|
||||
@@ -75,8 +75,8 @@ return [
|
||||
'reg_confirm_restrict_domain_placeholder' => 'Aucune restriction en place',
|
||||
|
||||
// Sorting Settings
|
||||
'sorting' => 'Lists & Sorting',
|
||||
'sorting_book_default' => 'Default Book Sort Rule',
|
||||
'sorting' => 'Listes et tri',
|
||||
'sorting_book_default' => 'Tri des livres par défaut',
|
||||
'sorting_book_default_desc' => 'Sélectionnez le tri par défaut à mettre en place sur les nouveaux livres. Cela n’affectera pas les livres existants, et peut être redéfini dans les livres.',
|
||||
'sorting_rules' => 'Règles de tri',
|
||||
'sorting_rules_desc' => 'Ce sont les opérations de tri qui peuvent être appliquées au contenu du système.',
|
||||
@@ -103,8 +103,8 @@ return [
|
||||
'sort_rule_op_updated_date' => 'Date de mise à jour',
|
||||
'sort_rule_op_chapters_first' => 'Chapitres en premier',
|
||||
'sort_rule_op_chapters_last' => 'Chapitres en dernier',
|
||||
'sorting_page_limits' => 'Per-Page Display Limits',
|
||||
'sorting_page_limits_desc' => 'Set how many items to show per-page in various lists within the system. Typically a lower amount will be more performant, while a higher amount avoids the need to click through multiple pages. Using an even multiple of 3 (18, 24, 30, etc...) is recommended.',
|
||||
'sorting_page_limits' => 'Limite d\'affichage par page',
|
||||
'sorting_page_limits_desc' => 'Définissez le nombre d’éléments à afficher par page dans les différentes listes du système. En général, un nombre plus faible offre de meilleures performances, tandis qu’un nombre plus élevé réduit le besoin de naviguer entre plusieurs pages. Il est recommandé d’utiliser un multiple pair de 3 (18, 24, 30, etc.).',
|
||||
|
||||
// Maintenance settings
|
||||
'maint' => 'Maintenance',
|
||||
@@ -197,13 +197,13 @@ return [
|
||||
'role_import_content' => 'Importer le contenu',
|
||||
'role_editor_change' => 'Changer l\'éditeur de page',
|
||||
'role_notifications' => 'Recevoir et gérer les notifications',
|
||||
'role_permission_note_users_and_roles' => 'These permissions will technically also provide visibility & searching of users & roles in the system.',
|
||||
'role_permission_note_users_and_roles' => 'Ces autorisations permettront également l\'accès à la consultation et la recherche des utilisateurs et des rôles dans le système.',
|
||||
'role_asset' => 'Permissions des ressources',
|
||||
'roles_system_warning' => 'Sachez que l\'accès à l\'une des trois permissions ci-dessus peut permettre à un utilisateur de modifier ses propres privilèges ou les privilèges des autres utilisateurs du système. N\'attribuez uniquement des rôles avec ces permissions qu\'à des utilisateurs de confiance.',
|
||||
'role_asset_desc' => 'Ces permissions contrôlent l\'accès par défaut des ressources dans le système. Les permissions dans les livres, les chapitres et les pages ignoreront ces permissions',
|
||||
'role_asset_admins' => 'Les administrateurs ont automatiquement accès à tous les contenus mais les options suivantes peuvent afficher ou masquer certaines options de l\'interface.',
|
||||
'role_asset_image_view_note' => 'Cela concerne la visibilité dans le gestionnaire d\'images. L\'accès réel des fichiers d\'image téléchargés dépendra de l\'option de stockage d\'images du système.',
|
||||
'role_asset_users_note' => 'These permissions will technically also provide visibility & searching of users in the system.',
|
||||
'role_asset_users_note' => 'Ces autorisations permettront également l\'accès à la consultation et la recherche des utilisateurs dans le système.',
|
||||
'role_all' => 'Tous',
|
||||
'role_own' => 'Propres',
|
||||
'role_controlled_by_asset' => 'Contrôlé par les ressources les ayant envoyés',
|
||||
@@ -270,7 +270,7 @@ return [
|
||||
'user_api_token_name_desc' => 'Donnez à votre jeton un nom lisible pour l\'identifier plus tard.',
|
||||
'user_api_token_expiry' => 'Date d\'expiration',
|
||||
'user_api_token_expiry_desc' => 'Définissez une date à laquelle ce jeton expire. Après cette date, les demandes effectuées à l\'aide de ce jeton ne fonctionneront plus. Le fait de laisser ce champ vide entraînera une expiration dans 100 ans.',
|
||||
'user_api_token_create_secret_message' => 'Immédiatement après la création de ce jeton, un "ID de jeton" "et" Secret de jeton "sera généré et affiché. Le secret ne sera affiché qu\'une seule fois, alors assurez-vous de copier la valeur dans un endroit sûr et sécurisé avant de continuer.',
|
||||
'user_api_token_create_secret_message' => 'Immédiatement après la création de ce jeton, un "ID de jeton" et "Secret de jeton" sera généré et affiché. Le secret ne sera affiché qu\'une seule fois, alors assurez-vous de copier la valeur dans un endroit sûr et sécurisé avant de continuer.',
|
||||
'user_api_token' => 'Jeton API',
|
||||
'user_api_token_id' => 'Token ID',
|
||||
'user_api_token_id_desc' => 'Il s\'agit d\'un identifiant généré par le système non modifiable pour ce jeton qui devra être fourni dans les demandes d\'API.',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Le fichier n\'a pas pu être envoyé. Le serveur peut ne pas accepter des fichiers de cette taille.',
|
||||
|
||||
'zip_file' => 'L\'attribut :attribute doit référencer un fichier dans le ZIP.',
|
||||
'zip_file_size' => 'Le fichier :attribute ne doit pas dépasser :size Mo.',
|
||||
'zip_file_mime' => ':attribute doit référencer un fichier de type :validTypes, trouvé :foundType.',
|
||||
'zip_model_expected' => 'Objet de données attendu, mais ":type" trouvé.',
|
||||
'zip_unique' => 'L\'attribut :attribute doit être unique pour le type d\'objet dans le ZIP.',
|
||||
|
||||
@@ -128,12 +128,12 @@ return [
|
||||
'comment_delete' => 'תגובה נמחקה',
|
||||
|
||||
// Sort Rules
|
||||
'sort_rule_create' => 'created sort rule',
|
||||
'sort_rule_create_notification' => 'Sort rule successfully created',
|
||||
'sort_rule_update' => 'updated sort rule',
|
||||
'sort_rule_update_notification' => 'Sort rule successfully updated',
|
||||
'sort_rule_delete' => 'deleted sort rule',
|
||||
'sort_rule_delete_notification' => 'Sort rule successfully deleted',
|
||||
'sort_rule_create' => 'נוצר חוק מיון',
|
||||
'sort_rule_create_notification' => 'חוק מיון נוצר בהצלחה',
|
||||
'sort_rule_update' => 'חוק מיון עודכן',
|
||||
'sort_rule_update_notification' => 'חוק מיון עודכן בהצלחה',
|
||||
'sort_rule_delete' => 'חוק מיון נמחק',
|
||||
'sort_rule_delete_notification' => 'חוק מיון נמחק בהצלחה',
|
||||
|
||||
// Other
|
||||
'permissions_update' => 'הרשאות עודכנו',
|
||||
|
||||
@@ -106,12 +106,13 @@ return [
|
||||
'mfa_verify_access' => 'אשר גישה',
|
||||
'mfa_verify_access_desc' => 'חשבון המשתמש שלך דורש ממך לאת את הזהות שלך בשכבת הגנה נוספת על מנת לאפשר לך גישה. יש לאשר גישה דרך אחד האמצעים הקיימים על מנת להמשיך.',
|
||||
'mfa_verify_no_methods' => 'אין אפשרויות אימות דו-שלבי מוגדרות',
|
||||
'mfa_verify_no_methods_desc' => 'No multi-factor authentication methods could be found for your account. You\'ll need to set up at least one method before you gain access.',
|
||||
'mfa_verify_no_methods_desc' => 'לא נמצאו אפשרויות ווידוא זהות עבור המשתמש שלך.
|
||||
נדרש לקנפג לפחות אחד על מנת לקבל גישה.',
|
||||
'mfa_verify_use_totp' => 'אמת באמצעות אפליקציה',
|
||||
'mfa_verify_use_backup_codes' => 'אמת באמצעות קוד גיבוי',
|
||||
'mfa_verify_backup_code' => 'קוד גיבוי',
|
||||
'mfa_verify_backup_code_desc' => 'הזן מטה אחד מקודי הגיבוי הנותרים לך:',
|
||||
'mfa_verify_backup_code_enter_here' => 'הזן קוד גיבוי כאן',
|
||||
'mfa_verify_totp_desc' => 'הזן את הקוד, שהונפק דרך האפליקציה שלך, מטה:',
|
||||
'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.',
|
||||
'mfa_setup_login_notification' => 'אמצעי זיהוי זהות הוגדרו, אנא התחבר מחדש.',
|
||||
];
|
||||
|
||||
@@ -30,8 +30,8 @@ return [
|
||||
'create' => 'צור',
|
||||
'update' => 'עדכן',
|
||||
'edit' => 'ערוך',
|
||||
'archive' => 'Archive',
|
||||
'unarchive' => 'Un-Archive',
|
||||
'archive' => 'הכנס לארכיון',
|
||||
'unarchive' => 'הוצא מארכיון',
|
||||
'sort' => 'מיין',
|
||||
'move' => 'הזז',
|
||||
'copy' => 'העתק',
|
||||
|
||||
@@ -22,8 +22,8 @@ return [
|
||||
'meta_created_name' => 'נוצר :timeLength על ידי :user',
|
||||
'meta_updated' => 'עודכן :timeLength',
|
||||
'meta_updated_name' => 'עודכן :timeLength על ידי :user',
|
||||
'meta_owned_name' => 'Owned by :user',
|
||||
'meta_reference_count' => 'Referenced by :count item|Referenced by :count items',
|
||||
'meta_owned_name' => 'בבעלות של :user',
|
||||
'meta_reference_count' => '',
|
||||
'entity_select' => 'בחר יישות',
|
||||
'entity_select_lack_permission' => 'אין לך אישורים דרושים לבחירת פריט זה',
|
||||
'images' => 'תמונות',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Could not read ZIP file.',
|
||||
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.',
|
||||
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Import ZIP failed to validate with errors:',
|
||||
'import_zip_failed_notification' => 'Failed to import ZIP file.',
|
||||
'import_perms_books' => 'You are lacking the required permissions to create books.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'The secret provided for the given used API token is incorrect',
|
||||
'api_user_no_api_permission' => 'The owner of the used API token does not have permission to make API calls',
|
||||
'api_user_token_expired' => 'The authorization token used has expired',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Error thrown when sending a test email:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'שדה :attribute ארעה שגיאה בעת ההעלאה.',
|
||||
|
||||
'zip_file' => 'The :attribute needs to reference a file within the ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Could not read ZIP file.',
|
||||
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.',
|
||||
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Import ZIP failed to validate with errors:',
|
||||
'import_zip_failed_notification' => 'Failed to import ZIP file.',
|
||||
'import_perms_books' => 'You are lacking the required permissions to create books.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Netočan API token',
|
||||
'api_user_no_api_permission' => 'Vlasnik API tokena nema potrebna dopuštenja',
|
||||
'api_user_token_expired' => 'Autorizacija je istekla',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Pogreška prilikom slanja testnog email:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Datoteka se ne može prenijeti. Server možda ne prihvaća datoteke te veličine.',
|
||||
|
||||
'zip_file' => 'The :attribute needs to reference a file within the ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
|
||||
@@ -85,12 +85,12 @@ return [
|
||||
'webhook_delete_notification' => 'Webhook sikeresen törölve',
|
||||
|
||||
// Imports
|
||||
'import_create' => 'created import',
|
||||
'import_create_notification' => 'Import successfully uploaded',
|
||||
'import_run' => 'updated import',
|
||||
'import_run_notification' => 'Content successfully imported',
|
||||
'import_delete' => 'deleted import',
|
||||
'import_delete_notification' => 'Import successfully deleted',
|
||||
'import_create' => 'import elkészült',
|
||||
'import_create_notification' => 'Az import sikeresen feltöltötve',
|
||||
'import_run' => 'import frissítve',
|
||||
'import_run_notification' => 'A tartalmat sikeresen importáltam.',
|
||||
'import_delete' => 'import törölve',
|
||||
'import_delete_notification' => 'Az import sikeresen törölve',
|
||||
|
||||
// Users
|
||||
'user_create' => 'létrehozta a felhasználót',
|
||||
|
||||
@@ -30,8 +30,8 @@ return [
|
||||
'create' => 'Létrehozás',
|
||||
'update' => 'Frissítés',
|
||||
'edit' => 'Szerkesztés',
|
||||
'archive' => 'Archive',
|
||||
'unarchive' => 'Un-Archive',
|
||||
'archive' => 'Archiválás',
|
||||
'unarchive' => 'Archiválás visszavonása',
|
||||
'sort' => 'Rendezés',
|
||||
'move' => 'Áthelyezés',
|
||||
'copy' => 'Másolás',
|
||||
@@ -111,5 +111,5 @@ return [
|
||||
'terms_of_service' => 'Felhasználási feltételek',
|
||||
|
||||
// OpenSearch
|
||||
'opensearch_description' => 'Search :appName',
|
||||
'opensearch_description' => 'Keresés :appName',
|
||||
];
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Could not read ZIP file.',
|
||||
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.',
|
||||
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Import ZIP failed to validate with errors:',
|
||||
'import_zip_failed_notification' => 'Failed to import ZIP file.',
|
||||
'import_perms_books' => 'You are lacking the required permissions to create books.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Az API tokenhez használt secret helytelen',
|
||||
'api_user_no_api_permission' => 'A használt API vezérjel tulajdonosának nincs jogosultsága API hívások végrehajtásához',
|
||||
'api_user_token_expired' => 'A használt hitelesítési vezérjel lejárt',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Hiba történt egy teszt email küldésekor:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'A fájlt nem lehet feltölteni. A kiszolgáló nem fogad el ilyen méretű fájlokat.',
|
||||
|
||||
'zip_file' => 'The :attribute needs to reference a file within the ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
|
||||
@@ -13,7 +13,7 @@ return [
|
||||
'image_intro_upload' => 'Unggah gambar baru dengan menyeret berkas gambar ke jendela ini, atau dengan menggunakan tombol "Unggah Gambar" di atas.',
|
||||
'image_all' => 'Semua',
|
||||
'image_all_title' => 'Lihat semua gambar',
|
||||
'image_book_title' => 'Lihat gambar yang diunggah ke buku ini',
|
||||
'image_book_title' => 'Lihat gambar untuk diunggah ke buku ini',
|
||||
'image_page_title' => 'Lihat gambar yang diunggah ke halaman ini',
|
||||
'image_search_hint' => 'Cari berdasarkan nama gambar',
|
||||
'image_uploaded' => 'Diunggah :uploadedDate',
|
||||
@@ -33,7 +33,7 @@ return [
|
||||
'image_update_success' => 'Detail gambar berhasil diperbarui',
|
||||
'image_delete_success' => 'Gambar berhasil dihapus',
|
||||
'image_replace' => 'Ganti Gambar',
|
||||
'image_replace_success' => 'Berkas gambar berhasil diperbarui',
|
||||
'image_replace_success' => 'Detail gambar berhasil diperbarui',
|
||||
'image_rebuild_thumbs' => 'Buat Ulang Variasi Ukuran',
|
||||
'image_rebuild_thumbs_success' => 'Variasi ukuran gambar berhasil dibuat ulang!',
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Tidak dapat membaca berkas ZIP.',
|
||||
'import_zip_cant_decode_data' => 'Tidak dapat menemukan dan mendekode konten ZIP data.json.',
|
||||
'import_zip_no_data' => 'Data berkas ZIP tidak berisi konten buku, bab, atau halaman yang diharapkan.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'Impor ZIP gagal divalidasi dengan kesalahan:',
|
||||
'import_zip_failed_notification' => 'Gagal mengimpor berkas ZIP.',
|
||||
'import_perms_books' => 'Anda tidak memiliki izin yang diperlukan untuk membuat buku.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Rahasia yang diberikan untuk token API bekas yang diberikan salah',
|
||||
'api_user_no_api_permission' => 'Pemilik token API yang digunakan tidak memiliki izin untuk melakukan panggilan API',
|
||||
'api_user_token_expired' => 'Token otorisasi yang digunakan telah kedaluwarsa',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Kesalahan dilempar saat mengirim email uji:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'Berkas tidak dapat diunggah. Server mungkin tidak menerima berkas dengan ukuran ini.',
|
||||
|
||||
'zip_file' => ':attribute perlu merujuk ke sebuah file yang terdapat di dalam arsip ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => ':attribute seharusnya berupa file dengan tipe :validTypes, tapi yang Anda unggah bertipe :foundType.',
|
||||
'zip_model_expected' => 'Diharapkan sebuah objek data, namun yang ditemukan adalah \':type\'.',
|
||||
'zip_unique' => ':attribute harus bersifat unik untuk setiap jenis objek dalam file ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Gat ekki lesið ZIP skrá.',
|
||||
'import_zip_cant_decode_data' => 'Fann ekki ZIP data.json innihald.',
|
||||
'import_zip_no_data' => 'ZIP skráin inniheldur ekkert efni.',
|
||||
'import_zip_data_too_large' => 'ZIP data.json content exceeds the configured application maximum upload size.',
|
||||
'import_validation_failed' => 'ZIP skráin stóðst ekki staðfestingu og skilaði villu:',
|
||||
'import_zip_failed_notification' => 'Gat ekki lesið inn ZIP skrá.',
|
||||
'import_perms_books' => 'Þú hefur ekki heimild til að búa til bækur.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Leyndarmálið sem gefið var upp fyrir API tókann er rangt',
|
||||
'api_user_no_api_permission' => 'Eigandi API tókans hefur ekki heimild til að gera API köll',
|
||||
'api_user_token_expired' => 'Auðkenningar tókin er útrunninn',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Villa kom upp viðað reyna senda prufu tölvupóst:',
|
||||
|
||||
@@ -106,6 +106,7 @@ return [
|
||||
'uploaded' => 'The file could not be uploaded. The server may not accept files of this size.',
|
||||
|
||||
'zip_file' => 'The :attribute needs to reference a file within the ZIP.',
|
||||
'zip_file_size' => 'The file :attribute must not exceed :size MB.',
|
||||
'zip_file_mime' => 'The :attribute needs to reference a file of type :validTypes, found :foundType.',
|
||||
'zip_model_expected' => 'Data object expected but ":type" found.',
|
||||
'zip_unique' => 'The :attribute must be unique for the object type within the ZIP.',
|
||||
|
||||
@@ -109,6 +109,7 @@ return [
|
||||
'import_zip_cant_read' => 'Impossibile leggere il file ZIP.',
|
||||
'import_zip_cant_decode_data' => 'Impossibile trovare e decodificare il contenuto ZIP data.json.',
|
||||
'import_zip_no_data' => 'I dati del file ZIP non hanno il contenuto previsto di libri, capitoli o pagine.',
|
||||
'import_zip_data_too_large' => 'Il contenuto ZIP data.json supera la dimensione massima di upload configurata nell\'applicazione.',
|
||||
'import_validation_failed' => 'L\'importazione ZIP non è stata convalidata con errori:',
|
||||
'import_zip_failed_notification' => 'Impossibile importare il file ZIP.',
|
||||
'import_perms_books' => 'Non hai i permessi necessari per creare libri.',
|
||||
@@ -124,6 +125,7 @@ return [
|
||||
'api_incorrect_token_secret' => 'Il token segreto fornito per il token API utilizzato non è corretto',
|
||||
'api_user_no_api_permission' => 'Il proprietario del token API utilizzato non ha il permesso di effettuare chiamate API',
|
||||
'api_user_token_expired' => 'Il token di autorizzazione utilizzato è scaduto',
|
||||
'api_cookie_auth_only_get' => 'Only GET requests are allowed when using the API with cookie-based authentication',
|
||||
|
||||
// Settings & Maintenance
|
||||
'maintenance_test_email_failure' => 'Si è verificato un errore durante l\'invio di una e-mail di prova:',
|
||||
|
||||
@@ -11,8 +11,8 @@ return [
|
||||
'updated_page_subject' => 'Pagina aggiornata: :pageName',
|
||||
'updated_page_intro' => 'Una pagina è stata aggiornata in :appName:',
|
||||
'updated_page_debounce' => 'Per evitare una massa di notifiche, per un po\' non ti verranno inviate notifiche per ulteriori modifiche a questa pagina dallo stesso editor.',
|
||||
'comment_mention_subject' => 'You have been mentioned in a comment on page: :pageName',
|
||||
'comment_mention_intro' => 'You were mentioned in a comment on :appName:',
|
||||
'comment_mention_subject' => 'Sei stato menzionato in un commento nella pagina: :pageName',
|
||||
'comment_mention_intro' => 'Sei stato menzionato in un commento su :appName:',
|
||||
|
||||
'detail_page_name' => 'Nome della pagina:',
|
||||
'detail_page_path' => 'Percorso della pagina:',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user