From 79f5be4170821644fe0597eb464853a5d411c2da Mon Sep 17 00:00:00 2001 From: Angelo Geant Gaviola <43493935+KiDxS@users.noreply.github.com> Date: Tue, 14 May 2024 17:04:23 +0800 Subject: [PATCH 01/11] Fixed notification preferences URL in email --- .../Notifications/Messages/BaseActivityNotification.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Activity/Notifications/Messages/BaseActivityNotification.php b/app/Activity/Notifications/Messages/BaseActivityNotification.php index ca86eb81b..067cd8f66 100644 --- a/app/Activity/Notifications/Messages/BaseActivityNotification.php +++ b/app/Activity/Notifications/Messages/BaseActivityNotification.php @@ -43,7 +43,7 @@ abstract class BaseActivityNotification extends MailNotification protected function buildReasonFooterLine(LocaleDefinition $locale): LinkedMailMessageLine { return new LinkedMailMessageLine( - url('/preferences/notifications'), + url('/my-account/notifications'), $locale->trans('notifications.footer_reason'), $locale->trans('notifications.footer_reason_link'), ); From 38913288d81fb1c8fcc62873499a9f31f4fe46e4 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 16 May 2024 14:15:26 +0100 Subject: [PATCH 02/11] Devdocs: Fixed visual theme system lang folder reference Made some other minor updates while there. Fixes #4998 --- dev/docs/visual-theme-system.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/docs/visual-theme-system.md b/dev/docs/visual-theme-system.md index 47ee57c0e..6e7105a9e 100644 --- a/dev/docs/visual-theme-system.md +++ b/dev/docs/visual-theme-system.md @@ -6,14 +6,14 @@ This theme system itself is maintained and supported but usages of this system, ## Getting Started -*[Video Guide](https://www.youtube.com/watch?v=gLy_2GBse48)* +*[Video Guide](https://foss.video/w/ibNY6bGmKFV1tva3Jz4KfA)* This makes use of the theme system. Create a folder for your theme within your BookStack `themes` directory. As an example we'll use `my_theme`, so we'd create a `themes/my_theme` folder. You'll need to tell BookStack to use your theme via the `APP_THEME` option in your `.env` file. For example: `APP_THEME=my_theme`. ## Customizing View Files -Content placed in your `themes//` folder will override the original view files found in the `resources/views` folder. These files are typically [Laravel Blade](https://laravel.com/docs/8.x/blade) files. +Content placed in your `themes//` folder will override the original view files found in the `resources/views` folder. These files are typically [Laravel Blade](https://laravel.com/docs/10.x/blade) files. As an example, I could override the `resources/views/books/parts/list-item.blade.php` file with my own template at the path `themes//books/parts/list-item.blade.php`. ## Customizing Icons @@ -22,7 +22,7 @@ SVG files placed in a `themes//icons` folder will override any icons ## Customizing Text Content -Folders with PHP translation files placed in a `themes//lang` folder will override translations defined within the `resources/lang` folder. Custom translations are merged with the original files so you only need to override the select translations you want to override, you don't need to copy the whole original file. Note that you'll need to include the language folder. +Folders with PHP translation files placed in a `themes//lang` folder will override translations defined within the `lang` folder. Custom translations are merged with the original files, so you only need to override the select translations you want to override, you don't need to copy the whole original file. Note that you'll need to include the language folder. As an example, Say I wanted to change 'Search' to 'Find'; Within a `themes//lang/en/common.php` file I'd set the following: From 570af500f4155488265d5606a1b31314c1b0c77b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 16 May 2024 14:54:44 +0100 Subject: [PATCH 03/11] WYSIWYG: Added justify cell range cleanup To help override & gain control of setting text alignment in tables. - Adds support of clearing "align" attributes in certain operations. - Updates cell range action handling to dedupe execcommand handling. - Adds clearing of additional alignment classes on direction control. Closes #5011 --- resources/js/wysiwyg/fixes.js | 91 ++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/resources/js/wysiwyg/fixes.js b/resources/js/wysiwyg/fixes.js index 61cace660..b6d627ff7 100644 --- a/resources/js/wysiwyg/fixes.js +++ b/resources/js/wysiwyg/fixes.js @@ -55,6 +55,19 @@ export function handleEmbedAlignmentChanges(editor) { }); } +/** + * Cleans up and removes text-alignment specific properties on all child elements. + * @param {HTMLElement} element + */ +function cleanChildAlignment(element) { + const alignedChildren = element.querySelectorAll('[align],[style*="text-align"],.align-center,.align-left,.align-right'); + for (const child of alignedChildren) { + child.removeAttribute('align'); + child.style.textAlign = null; + child.classList.remove('align-center', 'align-right', 'align-left'); + } +} + /** * Cleans up the direction property for an element. * Removes all inline direction control from child elements. @@ -62,16 +75,23 @@ export function handleEmbedAlignmentChanges(editor) { * @param {HTMLElement} element */ function cleanElementDirection(element) { - const directionChildren = element.querySelectorAll('[dir],[style*="direction"],[style*="text-align"]'); + const directionChildren = element.querySelectorAll('[dir],[style*="direction"]'); for (const child of directionChildren) { child.removeAttribute('dir'); child.style.direction = null; - child.style.textAlign = null; } + + cleanChildAlignment(element); element.style.direction = null; element.style.textAlign = null; + element.removeAttribute('align'); } +/** + * @typedef {Function} TableCellHandler + * @param {HTMLTableCellElement} cell + */ + /** * This tracks table cell range selection, so we can apply custom handling where * required to actions applied to such selections. @@ -90,34 +110,51 @@ export function handleTableCellRangeEvents(editor) { selectedCells = []; }); - // TinyMCE does not seem to do a great job on clearing styles in complex - // scenarios (like copied word content) when a range of table cells - // are selected. Here we watch for clear formatting events, so some manual - // cleanup can be performed. - const attrsToRemove = ['class', 'style', 'width', 'height']; - editor.on('ExecCommand', event => { - if (event.command === 'RemoveFormat') { - for (const cell of selectedCells) { - for (const attr of attrsToRemove) { - cell.removeAttribute(attr); - } + /** + * @type {Object} + */ + const actionByCommand = { + // TinyMCE does not seem to do a great job on clearing styles in complex + // scenarios (like copied word content) when a range of table cells + // are selected. Here we watch for clear formatting events, so some manual + // cleanup can be performed. + RemoveFormat: cell => { + const attrsToRemove = ['class', 'style', 'width', 'height', 'align']; + for (const attr of attrsToRemove) { + cell.removeAttribute(attr); } - } - }); + }, - // TinyMCE does not apply direction events to table cell range selections - // so here we hastily patch in that ability by setting the direction ourselves - // when a direction event is fired. - editor.on('ExecCommand', event => { - const command = event.command; - if (command !== 'mceDirectionLTR' && command !== 'mceDirectionRTL') { - return; - } - - const dir = command === 'mceDirectionLTR' ? 'ltr' : 'rtl'; - for (const cell of selectedCells) { - cell.setAttribute('dir', dir); + // TinyMCE does not apply direction events to table cell range selections + // so here we hastily patch in that ability by setting the direction ourselves + // when a direction event is fired. + mceDirectionLTR: cell => { + cell.setAttribute('dir', 'ltr'); cleanElementDirection(cell); + }, + mceDirectionRTL: cell => { + cell.setAttribute('dir', 'rtl'); + cleanElementDirection(cell); + }, + + // The "align" attribute can exist on table elements so this clears + // the attribute, and also clears common child alignment properties, + // when a text direction action is made for a table cell range. + JustifyLeft: cell => { + cell.removeAttribute('align'); + cleanChildAlignment(cell); + }, + JustifyRight: this.JustifyLeft, + JustifyCenter: this.JustifyLeft, + JustifyFull: this.JustifyLeft, + }; + + editor.on('ExecCommand', event => { + const action = actionByCommand[event.command]; + if (action) { + for (const cell of selectedCells) { + action(cell); + } } }); } From fc236f930b6836f49db1a584585581e70288af0a Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 18 May 2024 20:37:49 +0100 Subject: [PATCH 04/11] Dark Mode: Fixed setting labels missing dark mode handling Fixes #5018 --- resources/sass/_forms.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/sass/_forms.scss b/resources/sass/_forms.scss index e6d062ce8..a6f890e3c 100644 --- a/resources/sass/_forms.scss +++ b/resources/sass/_forms.scss @@ -321,6 +321,7 @@ input[type=color] { } } .setting-list-label { + @include lightDark(color, #222, #DDD); color: #222; font-size: 1rem; } From 5651d2c43d3e5e1ba34b74d566b017c45921f069 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 18 May 2024 20:40:26 +0100 Subject: [PATCH 05/11] Config: Reverted change to cache directory Change made during Laravel 10 updates to align (Laravel made this change much earlier in 5.x series) but it caused issues due to folder not pre-existing and due to potentiall permission issues. (CLI could create this during update, with non-compatible permissions for webserver). For #4999 --- app/Config/cache.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Config/cache.php b/app/Config/cache.php index 2ba16059a..b588437ff 100644 --- a/app/Config/cache.php +++ b/app/Config/cache.php @@ -53,8 +53,8 @@ return [ 'file' => [ 'driver' => 'file', - 'path' => storage_path('framework/cache/data'), - 'lock_path' => storage_path('framework/cache/data'), + 'path' => storage_path('framework/cache'), + 'lock_path' => storage_path('framework/cache'), ], 'memcached' => [ From 72c5141decb1d83910a81fd0c4bf77f4a463ce5c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 18 May 2024 21:18:15 +0100 Subject: [PATCH 06/11] File Uploads: Added basic validation response formatting Tested via app-level validation file limit, and then also with nginx file post limit. For #4996 --- resources/js/components/dropzone.js | 5 +---- resources/js/services/http.js | 29 +++++++++++++++++++++++++++++ resources/sass/_components.scss | 4 ++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/resources/js/components/dropzone.js b/resources/js/components/dropzone.js index 1cac09b4a..93e93a251 100644 --- a/resources/js/components/dropzone.js +++ b/resources/js/components/dropzone.js @@ -181,10 +181,7 @@ export class Dropzone extends Component { if (this.readyState === XMLHttpRequest.DONE && this.status === 200) { upload.markSuccess(component.successMessage); } else if (this.readyState === XMLHttpRequest.DONE && this.status >= 400) { - const content = this.responseText; - const data = content.startsWith('{') ? JSON.parse(content) : {message: content}; - const message = data?.message || data?.error || content; - upload.markError(message); + upload.markError(window.$http.formatErrorResponseText(this.responseText)); } }, }); diff --git a/resources/js/services/http.js b/resources/js/services/http.js index 49d5b6df4..d95e4a59a 100644 --- a/resources/js/services/http.js +++ b/resources/js/services/http.js @@ -207,3 +207,32 @@ async function performDelete(url, data = null) { } export {performDelete as delete}; + +/** + * Parse the response text for an error response to a user + * presentable string. Handles a range of errors responses including + * validation responses & server response text. + * @param {String} text + * @returns {String} + */ +export function formatErrorResponseText(text) { + const data = text.startsWith('{') ? JSON.parse(text) : {message: text}; + if (!data) { + return text; + } + + if (data.message || data.error) { + return data.message || data.error; + } + + const values = Object.values(data); + const isValidation = values.every(val => { + return Array.isArray(val) || val.every(x => typeof x === 'string'); + }); + + if (isValidation) { + return values.flat().join(' '); + } + + return text; +} diff --git a/resources/sass/_components.scss b/resources/sass/_components.scss index fc4ddeba4..18d1bc18f 100644 --- a/resources/sass/_components.scss +++ b/resources/sass/_components.scss @@ -321,6 +321,10 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { background-color: var(--color-primary); transition: width ease-in-out 240ms; } +.dropzone-file-item-label { + line-height: 1.2; + margin-bottom: .2rem; +} .dropzone-file-item-label, .dropzone-file-item-status { align-items: center; From 69af9e0dbdefd8c6c951e8afbe2bba141d454beb Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 20 May 2024 14:00:58 +0100 Subject: [PATCH 07/11] Routes: Added throttling to a range of auth-related endpoints Some already throttled in some means, but this adds a simple ip-based non-request-specific layer to many endpoints. Related to #4993 --- .../Controllers/ForgotPasswordController.php | 5 +++ .../Controllers/ResetPasswordController.php | 9 ++-- app/App/Providers/RouteServiceProvider.php | 4 ++ routes/web.php | 12 +++--- tests/Auth/RegistrationTest.php | 29 +++++++++++++ tests/Auth/ResetPasswordTest.php | 42 +++++++++++++++++++ tests/Auth/UserInviteTest.php | 20 +++++++++ 7 files changed, 109 insertions(+), 12 deletions(-) diff --git a/app/Access/Controllers/ForgotPasswordController.php b/app/Access/Controllers/ForgotPasswordController.php index 86fbe8fa3..36dd97755 100644 --- a/app/Access/Controllers/ForgotPasswordController.php +++ b/app/Access/Controllers/ForgotPasswordController.php @@ -6,6 +6,7 @@ use BookStack\Activity\ActivityType; use BookStack\Http\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\Password; +use Illuminate\Support\Sleep; class ForgotPasswordController extends Controller { @@ -32,6 +33,10 @@ class ForgotPasswordController extends Controller 'email' => ['required', 'email'], ]); + // Add random pause to the response to help avoid time-base sniffing + // of valid resets via slower email send handling. + Sleep::for(random_int(1000, 3000))->milliseconds(); + // We will send the password reset link to this user. Once we have attempted // to send the link, we will examine the response then see the message we // need to show to the user. Finally, we'll send out a proper response. diff --git a/app/Access/Controllers/ResetPasswordController.php b/app/Access/Controllers/ResetPasswordController.php index a8a45dddf..3af65d17f 100644 --- a/app/Access/Controllers/ResetPasswordController.php +++ b/app/Access/Controllers/ResetPasswordController.php @@ -15,14 +15,11 @@ use Illuminate\Validation\Rules\Password as PasswordRule; class ResetPasswordController extends Controller { - protected LoginService $loginService; - - public function __construct(LoginService $loginService) - { + public function __construct( + protected LoginService $loginService + ) { $this->middleware('guest'); $this->middleware('guard:standard'); - - $this->loginService = $loginService; } /** diff --git a/app/App/Providers/RouteServiceProvider.php b/app/App/Providers/RouteServiceProvider.php index 3a155920e..d7c1cb737 100644 --- a/app/App/Providers/RouteServiceProvider.php +++ b/app/App/Providers/RouteServiceProvider.php @@ -81,5 +81,9 @@ class RouteServiceProvider extends ServiceProvider RateLimiter::for('api', function (Request $request) { return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); }); + + RateLimiter::for('public', function (Request $request) { + return Limit::perMinute(10)->by($request->ip()); + }); } } diff --git a/routes/web.php b/routes/web.php index 03595288f..58b8f4e54 100644 --- a/routes/web.php +++ b/routes/web.php @@ -317,8 +317,8 @@ Route::get('/register/confirm', [AccessControllers\ConfirmEmailController::class Route::get('/register/confirm/awaiting', [AccessControllers\ConfirmEmailController::class, 'showAwaiting']); Route::post('/register/confirm/resend', [AccessControllers\ConfirmEmailController::class, 'resend']); Route::get('/register/confirm/{token}', [AccessControllers\ConfirmEmailController::class, 'showAcceptForm']); -Route::post('/register/confirm/accept', [AccessControllers\ConfirmEmailController::class, 'confirm']); -Route::post('/register', [AccessControllers\RegisterController::class, 'postRegister']); +Route::post('/register/confirm/accept', [AccessControllers\ConfirmEmailController::class, 'confirm'])->middleware('throttle:public'); +Route::post('/register', [AccessControllers\RegisterController::class, 'postRegister'])->middleware('throttle:public'); // SAML routes Route::post('/saml2/login', [AccessControllers\Saml2Controller::class, 'login']); @@ -338,16 +338,16 @@ Route::get('/oidc/callback', [AccessControllers\OidcController::class, 'callback Route::post('/oidc/logout', [AccessControllers\OidcController::class, 'logout']); // User invitation routes -Route::get('/register/invite/{token}', [AccessControllers\UserInviteController::class, 'showSetPassword']); -Route::post('/register/invite/{token}', [AccessControllers\UserInviteController::class, 'setPassword']); +Route::get('/register/invite/{token}', [AccessControllers\UserInviteController::class, 'showSetPassword'])->middleware('throttle:public'); +Route::post('/register/invite/{token}', [AccessControllers\UserInviteController::class, 'setPassword'])->middleware('throttle:public'); // Password reset link request routes Route::get('/password/email', [AccessControllers\ForgotPasswordController::class, 'showLinkRequestForm']); -Route::post('/password/email', [AccessControllers\ForgotPasswordController::class, 'sendResetLinkEmail']); +Route::post('/password/email', [AccessControllers\ForgotPasswordController::class, 'sendResetLinkEmail'])->middleware('throttle:public'); // Password reset routes Route::get('/password/reset/{token}', [AccessControllers\ResetPasswordController::class, 'showResetForm']); -Route::post('/password/reset', [AccessControllers\ResetPasswordController::class, 'reset']); +Route::post('/password/reset', [AccessControllers\ResetPasswordController::class, 'reset'])->middleware('throttle:public'); // Metadata routes Route::view('/help/wysiwyg', 'help.wysiwyg'); diff --git a/tests/Auth/RegistrationTest.php b/tests/Auth/RegistrationTest.php index 60ae17573..42d1120e4 100644 --- a/tests/Auth/RegistrationTest.php +++ b/tests/Auth/RegistrationTest.php @@ -203,4 +203,33 @@ class RegistrationTest extends TestCase $resp = $this->followRedirects($resp); $this->withHtml($resp)->assertElementExists('form input[name="username"].text-neg'); } + + public function test_registration_endpoint_throttled() + { + $this->setSettings(['registration-enabled' => 'true']); + + for ($i = 0; $i < 11; $i++) { + $response = $this->post('/register/', [ + 'name' => "Barry{$i}", + 'email' => "barry{$i}@example.com", + 'password' => "barryIsTheBest{$i}", + ]); + auth()->logout(); + } + + $response->assertStatus(429); + } + + public function test_registration_confirmation_throttled() + { + $this->setSettings(['registration-enabled' => 'true']); + + for ($i = 0; $i < 11; $i++) { + $response = $this->post('/register/confirm/accept', [ + 'token' => "token{$i}", + ]); + } + + $response->assertStatus(429); + } } diff --git a/tests/Auth/ResetPasswordTest.php b/tests/Auth/ResetPasswordTest.php index d2af17b9c..026f8c5ba 100644 --- a/tests/Auth/ResetPasswordTest.php +++ b/tests/Auth/ResetPasswordTest.php @@ -4,11 +4,19 @@ namespace Tests\Auth; use BookStack\Access\Notifications\ResetPasswordNotification; use BookStack\Users\Models\User; +use Carbon\CarbonInterval; use Illuminate\Support\Facades\Notification; +use Illuminate\Support\Sleep; use Tests\TestCase; class ResetPasswordTest extends TestCase { + protected function setUp(): void + { + parent::setUp(); + Sleep::fake(); + } + public function test_reset_flow() { Notification::fake(); @@ -75,6 +83,17 @@ class ResetPasswordTest extends TestCase ->assertSee('The password reset token is invalid for this email address.'); } + public function test_reset_request_with_not_found_user_still_has_delay() + { + $this->followingRedirects()->post('/password/email', [ + 'email' => 'barrynotfoundrandomuser@example.com', + ]); + + Sleep::assertSlept(function (CarbonInterval $duration): bool { + return $duration->totalMilliseconds > 999; + }, 1); + } + public function test_reset_page_shows_sign_links() { $this->setSettings(['registration-enabled' => 'true']); @@ -98,4 +117,27 @@ class ResetPasswordTest extends TestCase Notification::assertSentTimes(ResetPasswordNotification::class, 1); $resp->assertSee('A password reset link will be sent to ' . $editor->email . ' if that email address is found in the system.'); } + + public function test_reset_request_with_not_found_user_is_throttled() + { + for ($i = 0; $i < 11; $i++) { + $response = $this->post('/password/email', [ + 'email' => 'barrynotfoundrandomuser@example.com', + ]); + } + + $response->assertStatus(429); + } + + public function test_reset_call_is_throttled() + { + for ($i = 0; $i < 11; $i++) { + $response = $this->post('/password/reset', [ + 'email' => "arandomuser{$i}@example.com", + 'token' => "randomtoken{$i}", + ]); + } + + $response->assertStatus(429); + } } diff --git a/tests/Auth/UserInviteTest.php b/tests/Auth/UserInviteTest.php index a9dee0007..434de6aa6 100644 --- a/tests/Auth/UserInviteTest.php +++ b/tests/Auth/UserInviteTest.php @@ -137,4 +137,24 @@ class UserInviteTest extends TestCase $setPasswordPageResp->assertRedirect('/password/email'); $setPasswordPageResp->assertSessionHas('error', 'This invitation link has expired. You can instead try to reset your account password.'); } + + public function test_set_password_view_is_throttled() + { + for ($i = 0; $i < 11; $i++) { + $response = $this->get("/register/invite/tokenhere{$i}"); + } + + $response->assertStatus(429); + } + + public function test_set_password_post_is_throttled() + { + for ($i = 0; $i < 11; $i++) { + $response = $this->post("/register/invite/tokenhere{$i}", [ + 'password' => 'my test password', + ]); + } + + $response->assertStatus(429); + } } From d133f904d369cf2ca964a5c9f54e4e19843507c2 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 20 May 2024 17:23:15 +0100 Subject: [PATCH 08/11] Auth: Changed email confirmations to use login attempt user Negates the need for a public confirmation resend form since we can instead just send direct to the last session login attempter. --- .../Controllers/ConfirmEmailController.php | 25 +++++--- .../Controllers/HandlesPartialLogins.php | 2 +- app/Access/EmailConfirmationService.php | 2 +- .../StoppedAuthenticationException.php | 14 ++--- lang/en/errors.php | 1 + ...hp => register-confirm-awaiting.blade.php} | 10 +--- tests/Auth/RegistrationTest.php | 58 +++++++++++++++++++ 7 files changed, 83 insertions(+), 29 deletions(-) rename resources/views/auth/{user-unconfirmed.blade.php => register-confirm-awaiting.blade.php} (66%) diff --git a/app/Access/Controllers/ConfirmEmailController.php b/app/Access/Controllers/ConfirmEmailController.php index 94647e06e..d71b8f450 100644 --- a/app/Access/Controllers/ConfirmEmailController.php +++ b/app/Access/Controllers/ConfirmEmailController.php @@ -32,13 +32,17 @@ class ConfirmEmailController extends Controller /** * Shows a notice that a user's email address has not been confirmed, - * Also has the option to re-send the confirmation email. + * along with the option to re-send the confirmation email. */ public function showAwaiting() { $user = $this->loginService->getLastLoginAttemptUser(); + if ($user === null) { + $this->showErrorNotification(trans('errors.login_user_not_found')); + return redirect('/login'); + } - return view('auth.user-unconfirmed', ['user' => $user]); + return view('auth.register-confirm-awaiting'); } /** @@ -90,19 +94,24 @@ class ConfirmEmailController extends Controller /** * Resend the confirmation email. */ - public function resend(Request $request) + public function resend() { - $this->validate($request, [ - 'email' => ['required', 'email', 'exists:users,email'], - ]); - $user = $this->userRepo->getByEmail($request->get('email')); + $user = $this->loginService->getLastLoginAttemptUser(); + if ($user === null) { + $this->showErrorNotification(trans('errors.login_user_not_found')); + return redirect('/login'); + } try { $this->emailConfirmationService->sendConfirmation($user); + } catch (ConfirmationEmailException $e) { + $this->showErrorNotification($e->getMessage()); + + return redirect('/login'); } catch (Exception $e) { $this->showErrorNotification(trans('auth.email_confirm_send_error')); - return redirect('/register/confirm'); + return redirect('/register/awaiting'); } $this->showSuccessNotification(trans('auth.email_confirm_resent')); diff --git a/app/Access/Controllers/HandlesPartialLogins.php b/app/Access/Controllers/HandlesPartialLogins.php index c5554e473..47a63d19b 100644 --- a/app/Access/Controllers/HandlesPartialLogins.php +++ b/app/Access/Controllers/HandlesPartialLogins.php @@ -17,7 +17,7 @@ trait HandlesPartialLogins $user = auth()->user() ?? $loginService->getLastLoginAttemptUser(); if (!$user) { - throw new NotFoundException('A user for this action could not be found'); + throw new NotFoundException(trans('errors.login_user_not_found')); } return $user; diff --git a/app/Access/EmailConfirmationService.php b/app/Access/EmailConfirmationService.php index de9ea69b8..1a5156d3e 100644 --- a/app/Access/EmailConfirmationService.php +++ b/app/Access/EmailConfirmationService.php @@ -17,7 +17,7 @@ class EmailConfirmationService extends UserTokenService * * @throws ConfirmationEmailException */ - public function sendConfirmation(User $user) + public function sendConfirmation(User $user): void { if ($user->email_confirmed) { throw new ConfirmationEmailException(trans('errors.email_already_confirmed'), '/login'); diff --git a/app/Exceptions/StoppedAuthenticationException.php b/app/Exceptions/StoppedAuthenticationException.php index 51e48aa1c..8a917bc52 100644 --- a/app/Exceptions/StoppedAuthenticationException.php +++ b/app/Exceptions/StoppedAuthenticationException.php @@ -9,16 +9,10 @@ use Illuminate\Http\Request; class StoppedAuthenticationException extends \Exception implements Responsable { - protected $user; - protected $loginService; - - /** - * StoppedAuthenticationException constructor. - */ - public function __construct(User $user, LoginService $loginService) - { - $this->user = $user; - $this->loginService = $loginService; + public function __construct( + protected User $user, + protected LoginService $loginService + ) { parent::__construct(); } diff --git a/lang/en/errors.php b/lang/en/errors.php index 8773a78cb..752eb5672 100644 --- a/lang/en/errors.php +++ b/lang/en/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Social driver not found', 'social_driver_not_configured' => 'Your :socialAccount social settings are not configured correctly.', 'invite_token_expired' => 'This invitation link has expired. You can instead try to reset your account password.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'File path :filePath could not be uploaded to. Ensure it is writable to the server.', diff --git a/resources/views/auth/user-unconfirmed.blade.php b/resources/views/auth/register-confirm-awaiting.blade.php similarity index 66% rename from resources/views/auth/user-unconfirmed.blade.php rename to resources/views/auth/register-confirm-awaiting.blade.php index 2f780b8a3..e5d6f61b2 100644 --- a/resources/views/auth/user-unconfirmed.blade.php +++ b/resources/views/auth/register-confirm-awaiting.blade.php @@ -14,15 +14,7 @@

- {!! csrf_field() !!} -
- - @if($user) - @include('form.text', ['name' => 'email', 'model' => $user]) - @else - @include('form.text', ['name' => 'email']) - @endif -
+ {{ csrf_field() }}
diff --git a/tests/Auth/RegistrationTest.php b/tests/Auth/RegistrationTest.php index 42d1120e4..2666fa3b4 100644 --- a/tests/Auth/RegistrationTest.php +++ b/tests/Auth/RegistrationTest.php @@ -25,6 +25,9 @@ class RegistrationTest extends TestCase $resp->assertRedirect('/register/confirm'); $this->assertDatabaseHas('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]); + $resp = $this->get('/register/confirm'); + $resp->assertSee('Thanks for registering!'); + // Ensure notification sent /** @var User $dbUser */ $dbUser = User::query()->where('email', '=', $user->email)->first(); @@ -232,4 +235,59 @@ class RegistrationTest extends TestCase $response->assertStatus(429); } + + public function test_registration_confirmation_resend() + { + Notification::fake(); + $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']); + $user = User::factory()->make(); + + $resp = $this->post('/register', $user->only('name', 'email', 'password')); + $resp->assertRedirect('/register/confirm'); + $dbUser = User::query()->where('email', '=', $user->email)->first(); + + $resp = $this->post('/login', ['email' => $user->email, 'password' => $user->password]); + $resp->assertRedirect('/register/confirm/awaiting'); + + $resp = $this->post('/register/confirm/resend'); + $resp->assertRedirect('/register/confirm'); + Notification::assertSentToTimes($dbUser, ConfirmEmailNotification::class, 2); + } + + public function test_registration_confirmation_expired_resend() + { + Notification::fake(); + $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']); + $user = User::factory()->make(); + + $resp = $this->post('/register', $user->only('name', 'email', 'password')); + $resp->assertRedirect('/register/confirm'); + $dbUser = User::query()->where('email', '=', $user->email)->first(); + + $resp = $this->post('/login', ['email' => $user->email, 'password' => $user->password]); + $resp->assertRedirect('/register/confirm/awaiting'); + + $emailConfirmation = DB::table('email_confirmations')->where('user_id', '=', $dbUser->id)->first(); + $this->travel(2)->days(); + + $resp = $this->post("/register/confirm/accept", [ + 'token' => $emailConfirmation->token, + ]); + $resp->assertRedirect('/register/confirm'); + $this->assertSessionError('The confirmation token has expired, A new confirmation email has been sent.'); + + Notification::assertSentToTimes($dbUser, ConfirmEmailNotification::class, 2); + } + + public function test_registration_confirmation_awaiting_and_resend_returns_to_log_if_no_login_attempt_user_found() + { + $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']); + + $this->get('/register/confirm/awaiting')->assertRedirect('/login'); + $this->assertSessionError('A user for this action could not be found.'); + $this->flushSession(); + + $this->post('/register/confirm/resend')->assertRedirect('/login'); + $this->assertSessionError('A user for this action could not be found.'); + } } From bdfa76ed9ae835d59a7cf52737ea331027770aba Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 20 May 2024 17:28:53 +0100 Subject: [PATCH 09/11] Deps: Updated php/composer packages --- composer.lock | 122 +++++++++++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/composer.lock b/composer.lock index b5b08a902..481475995 100644 --- a/composer.lock +++ b/composer.lock @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.305.9", + "version": "3.307.1", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "a611af9a40a5d93f2f04427b322dbb6044e90327" + "reference": "cc79f16e1a1bd3feee421401ba2f21915abfdf91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a611af9a40a5d93f2f04427b322dbb6044e90327", - "reference": "a611af9a40a5d93f2f04427b322dbb6044e90327", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/cc79f16e1a1bd3feee421401ba2f21915abfdf91", + "reference": "cc79f16e1a1bd3feee421401ba2f21915abfdf91", "shasum": "" }, "require": { @@ -151,9 +151,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.305.9" + "source": "https://github.com/aws/aws-sdk-php/tree/3.307.1" }, - "time": "2024-05-03T18:09:03+00:00" + "time": "2024-05-17T18:07:44+00:00" }, { "name": "bacon/bacon-qr-code", @@ -1167,26 +1167,26 @@ }, { "name": "firebase/php-jwt", - "version": "v6.10.0", + "version": "v6.10.1", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "a49db6f0a5033aef5143295342f1c95521b075ff" + "reference": "500501c2ce893c824c801da135d02661199f60c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/a49db6f0a5033aef5143295342f1c95521b075ff", - "reference": "a49db6f0a5033aef5143295342f1c95521b075ff", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/500501c2ce893c824c801da135d02661199f60c5", + "reference": "500501c2ce893c824c801da135d02661199f60c5", "shasum": "" }, "require": { - "php": "^7.4||^8.0" + "php": "^8.0" }, "require-dev": { - "guzzlehttp/guzzle": "^6.5||^7.4", + "guzzlehttp/guzzle": "^7.4", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.5", - "psr/cache": "^1.0||^2.0", + "psr/cache": "^2.0||^3.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0" }, @@ -1224,9 +1224,9 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.10.0" + "source": "https://github.com/firebase/php-jwt/tree/v6.10.1" }, - "time": "2023-12-01T16:26:39+00:00" + "time": "2024-05-18T18:05:11+00:00" }, { "name": "fruitcake/php-cors", @@ -1838,16 +1838,16 @@ }, { "name": "intervention/image", - "version": "3.6.3", + "version": "3.6.4", "source": { "type": "git", "url": "https://github.com/Intervention/image.git", - "reference": "2dbfb53bf8909257e710cf6091d10a9ca7500742" + "reference": "193324ec88bc5ad4039e57ce9b926ae28dfde813" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/image/zipball/2dbfb53bf8909257e710cf6091d10a9ca7500742", - "reference": "2dbfb53bf8909257e710cf6091d10a9ca7500742", + "url": "https://api.github.com/repos/Intervention/image/zipball/193324ec88bc5ad4039e57ce9b926ae28dfde813", + "reference": "193324ec88bc5ad4039e57ce9b926ae28dfde813", "shasum": "" }, "require": { @@ -1894,7 +1894,7 @@ ], "support": { "issues": "https://github.com/Intervention/image/issues", - "source": "https://github.com/Intervention/image/tree/3.6.3" + "source": "https://github.com/Intervention/image/tree/3.6.4" }, "funding": [ { @@ -1906,7 +1906,7 @@ "type": "github" } ], - "time": "2024-05-02T09:03:18+00:00" + "time": "2024-05-08T13:53:15+00:00" }, { "name": "knplabs/knp-snappy", @@ -2302,16 +2302,16 @@ }, { "name": "laravel/socialite", - "version": "v5.13.2", + "version": "v5.14.0", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "278d4615f68205722b3a129135774b3764b28a90" + "reference": "c7b0193a3753a29aff8ce80aa2f511917e6ed68a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/278d4615f68205722b3a129135774b3764b28a90", - "reference": "278d4615f68205722b3a129135774b3764b28a90", + "url": "https://api.github.com/repos/laravel/socialite/zipball/c7b0193a3753a29aff8ce80aa2f511917e6ed68a", + "reference": "c7b0193a3753a29aff8ce80aa2f511917e6ed68a", "shasum": "" }, "require": { @@ -2370,7 +2370,7 @@ "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" }, - "time": "2024-04-26T13:48:16+00:00" + "time": "2024-05-03T20:31:38+00:00" }, { "name": "laravel/tinker", @@ -3822,16 +3822,16 @@ }, { "name": "paragonie/constant_time_encoding", - "version": "v2.6.3", + "version": "v2.7.0", "source": { "type": "git", "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "58c3f47f650c94ec05a151692652a868995d2938" + "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/58c3f47f650c94ec05a151692652a868995d2938", - "reference": "58c3f47f650c94ec05a151692652a868995d2938", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/52a0d99e69f56b9ec27ace92ba56897fe6993105", + "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105", "shasum": "" }, "require": { @@ -3885,7 +3885,7 @@ "issues": "https://github.com/paragonie/constant_time_encoding/issues", "source": "https://github.com/paragonie/constant_time_encoding" }, - "time": "2022-06-14T06:56:20+00:00" + "time": "2024-05-08T12:18:48+00:00" }, { "name": "paragonie/random_compat", @@ -4579,20 +4579,20 @@ }, { "name": "psr/http-factory", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", + "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", @@ -4616,7 +4616,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -4628,9 +4628,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-04-10T20:10:41+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", @@ -8326,16 +8326,16 @@ }, { "name": "larastan/larastan", - "version": "v2.9.5", + "version": "v2.9.6", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "101f1a4470f87326f4d3995411d28679d8800abe" + "reference": "93d5b95d2e29cdb8203363d44abfdbc0bc7ef57f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/101f1a4470f87326f4d3995411d28679d8800abe", - "reference": "101f1a4470f87326f4d3995411d28679d8800abe", + "url": "https://api.github.com/repos/larastan/larastan/zipball/93d5b95d2e29cdb8203363d44abfdbc0bc7ef57f", + "reference": "93d5b95d2e29cdb8203363d44abfdbc0bc7ef57f", "shasum": "" }, "require": { @@ -8404,7 +8404,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v2.9.5" + "source": "https://github.com/larastan/larastan/tree/v2.9.6" }, "funding": [ { @@ -8424,20 +8424,20 @@ "type": "patreon" } ], - "time": "2024-04-16T19:13:34+00:00" + "time": "2024-05-09T11:53:26+00:00" }, { "name": "mockery/mockery", - "version": "1.6.11", + "version": "1.6.12", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "81a161d0b135df89951abd52296adf97deb0723d" + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/81a161d0b135df89951abd52296adf97deb0723d", - "reference": "81a161d0b135df89951abd52296adf97deb0723d", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", "shasum": "" }, "require": { @@ -8507,7 +8507,7 @@ "security": "https://github.com/mockery/mockery/security/advisories", "source": "https://github.com/mockery/mockery" }, - "time": "2024-03-21T18:34:15+00:00" + "time": "2024-05-16T03:13:13+00:00" }, { "name": "myclabs/deep-copy", @@ -8872,16 +8872,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.67", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493" + "reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/16ddbe776f10da6a95ebd25de7c1dbed397dc493", - "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e524358f930e41a2b4cca1320e3b04fc26b39e0b", + "reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b", "shasum": "" }, "require": { @@ -8926,7 +8926,7 @@ "type": "github" } ], - "time": "2024-04-16T07:22:02+00:00" + "time": "2024-05-15T08:00:59+00:00" }, { "name": "phpunit/php-code-coverage", @@ -10268,16 +10268,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.9.2", + "version": "3.10.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480" + "reference": "57e09801c2fbae2d257b8b75bebb3deeb7e9deb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/aac1f6f347a5c5ac6bc98ad395007df00990f480", - "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/57e09801c2fbae2d257b8b75bebb3deeb7e9deb2", + "reference": "57e09801c2fbae2d257b8b75bebb3deeb7e9deb2", "shasum": "" }, "require": { @@ -10344,7 +10344,7 @@ "type": "open_collective" } ], - "time": "2024-04-23T20:25:34+00:00" + "time": "2024-05-20T08:11:32+00:00" }, { "name": "ssddanbrown/asserthtml", @@ -10541,5 +10541,5 @@ "platform-overrides": { "php": "8.1.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From 586e8963a8f47c5fff65a44e1e6bf2db92bc1d35 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 21 May 2024 11:04:27 +0100 Subject: [PATCH 10/11] Updated translations with latest Crowdin changes (#4994) --- lang/ar/common.php | 2 +- lang/ar/errors.php | 1 + lang/bg/errors.php | 1 + lang/bs/errors.php | 1 + lang/ca/errors.php | 1 + lang/cs/errors.php | 1 + lang/cy/errors.php | 1 + lang/da/errors.php | 1 + lang/de/errors.php | 1 + lang/de_informal/errors.php | 1 + lang/de_informal/settings.php | 2 +- lang/el/errors.php | 1 + lang/es/errors.php | 1 + lang/es_AR/activities.php | 6 +++--- lang/es_AR/common.php | 10 +++++----- lang/es_AR/components.php | 2 +- lang/es_AR/editor.php | 4 ++-- lang/es_AR/errors.php | 1 + lang/et/errors.php | 1 + lang/eu/errors.php | 1 + lang/fa/errors.php | 1 + lang/fi/errors.php | 1 + lang/fr/errors.php | 1 + lang/fr/settings.php | 2 +- lang/he/activities.php | 8 ++++---- lang/he/errors.php | 1 + lang/hr/errors.php | 1 + lang/hu/common.php | 2 +- lang/hu/errors.php | 1 + lang/hu/preferences.php | 2 +- lang/hu/settings.php | 16 ++++++++-------- lang/id/errors.php | 1 + lang/it/errors.php | 1 + lang/ja/errors.php | 1 + lang/ka/errors.php | 1 + lang/ko/errors.php | 1 + lang/lt/errors.php | 1 + lang/lv/errors.php | 1 + lang/nb/errors.php | 1 + lang/nl/activities.php | 14 +++++++------- lang/nl/auth.php | 26 +++++++++++++------------- lang/nl/editor.php | 2 +- lang/nl/entities.php | 10 +++++----- lang/nl/errors.php | 1 + lang/nl/settings.php | 2 +- lang/nn/errors.php | 1 + lang/pl/errors.php | 1 + lang/pt/errors.php | 1 + lang/pt_BR/errors.php | 1 + lang/ro/errors.php | 1 + lang/ru/errors.php | 1 + lang/sk/errors.php | 1 + lang/sl/errors.php | 1 + lang/sq/errors.php | 1 + lang/sr/errors.php | 1 + lang/sv/editor.php | 10 +++++----- lang/sv/errors.php | 1 + lang/sv/settings.php | 20 ++++++++++---------- lang/tr/errors.php | 1 + lang/uk/errors.php | 1 + lang/uz/errors.php | 1 + lang/vi/errors.php | 1 + lang/zh_CN/errors.php | 1 + lang/zh_TW/errors.php | 1 + lang/zh_TW/settings.php | 13 +++++++------ 65 files changed, 123 insertions(+), 76 deletions(-) diff --git a/lang/ar/common.php b/lang/ar/common.php index 740b1fbbb..02868b565 100644 --- a/lang/ar/common.php +++ b/lang/ar/common.php @@ -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 بكسل، على الرغم من أنه سيتم تحجيمها وقصها بشكل مرن لتناسب واجهة المستخدم في سيناريوهات مختلفة حسب الحاجة، لذا فإن الأبعاد الفعلية للعرض ستختلف.', // Actions 'actions' => 'إجراءات', diff --git a/lang/ar/errors.php b/lang/ar/errors.php index e1d968a03..9ffc4c175 100644 --- a/lang/ar/errors.php +++ b/lang/ar/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'لم يتم العثور على السوشيال درايفر "Social driver"', 'social_driver_not_configured' => 'لم يتم تهيئة إعدادات حسابك الاجتماعي بشكل صحيح.', 'invite_token_expired' => 'انتهت صلاحية رابط هذه الدعوة. يمكنك بدلاً من ذلك محاولة إعادة تعيين كلمة مرور حسابك.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'لا يمكن الرفع إلى مسار :filePath. الرجاء التأكد من قابلية الكتابة إلى الخادم.', diff --git a/lang/bg/errors.php b/lang/bg/errors.php index 6b9d8a20c..8272683db 100644 --- a/lang/bg/errors.php +++ b/lang/bg/errors.php @@ -37,6 +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.', // System 'path_not_writable' => 'Не може да се качи файл в :filePath. Увери се на сървъра, че в пътя може да се записва.', diff --git a/lang/bs/errors.php b/lang/bs/errors.php index bcf60a323..2dd0f94ef 100644 --- a/lang/bs/errors.php +++ b/lang/bs/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Driver društvene mreže nije pronađen', 'social_driver_not_configured' => 'Vaše :socialAccount postavke nisu konfigurisane ispravno.', 'invite_token_expired' => 'Pozivni link je istekao. Možete umjesto toga pokušati da resetujete lozinku.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Na putanju fajla :filePath se ne može učitati. Potvrdite da je omogućeno pisanje na server.', diff --git a/lang/ca/errors.php b/lang/ca/errors.php index 46943fdb1..565527696 100644 --- a/lang/ca/errors.php +++ b/lang/ca/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'No s’ha trobat el controlador social', 'social_driver_not_configured' => 'La configuració social de :socialAccount no és correcta.', 'invite_token_expired' => 'Aquest enllaç d’invitació ha caducat. Podeu provar de restablir la contrasenya del vostre compte.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'No s’ha pogut pujar al camí del fitxer :filePath. Assegureu-vos que el servidor hi té permisos d’escriptura.', diff --git a/lang/cs/errors.php b/lang/cs/errors.php index 2ee281c3e..37b9348a2 100644 --- a/lang/cs/errors.php +++ b/lang/cs/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Doplněk pro tohoto správce identity nebyl nalezen.', 'social_driver_not_configured' => 'Nastavení vašeho účtu na :socialAccount není správné. :socialAccount musí mít vaše svolení pro naší aplikaci vás přihlásit.', 'invite_token_expired' => 'Odkaz v pozvánce již bohužel vypršel. Namísto toho ale můžete zkusit resetovat heslo do Vašeho účtu.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Nelze zapisovat na cestu k souboru :filePath. Zajistěte aby se dalo nahrávat na server.', diff --git a/lang/cy/errors.php b/lang/cy/errors.php index a2c8fada5..71a47bc40 100644 --- a/lang/cy/errors.php +++ b/lang/cy/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Gyrrwr cymdeithasol heb ei ganfod', 'social_driver_not_configured' => 'Nid yw eich gosodiadau cymdeithasol :socialAccount wedi\'u ffurfweddu\'n gywir.', 'invite_token_expired' => 'Mae\'r ddolen wahoddiad hon wedi dod i ben. Yn lle hynny, gallwch chi geisio ailosod cyfrinair eich cyfrif.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Nid oedd modd uwchlwytho llwybr ffeil :filePath. Sicrhewch ei fod yn ysgrifenadwy i\'r gweinydd.', diff --git a/lang/da/errors.php b/lang/da/errors.php index bc27a9023..dbee71251 100644 --- a/lang/da/errors.php +++ b/lang/da/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Socialdriver ikke fundet', 'social_driver_not_configured' => 'Dine :socialAccount indstillinger er ikke konfigureret korret.', 'invite_token_expired' => 'Dette invitationslink er udløbet. I stedet kan du prøve at nulstille din kontos kodeord.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Filsti :filePath kunne ikke uploades til. Sørg for at den kan skrives til af webserveren.', diff --git a/lang/de/errors.php b/lang/de/errors.php index 8cfddacd8..5ba185ee6 100644 --- a/lang/de/errors.php +++ b/lang/de/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Treiber für Social-Media-Konten nicht gefunden', 'social_driver_not_configured' => 'Ihr :socialAccount-Konto ist nicht korrekt konfiguriert.', 'invite_token_expired' => 'Dieser Einladungslink ist abgelaufen. Sie können stattdessen versuchen Ihr Passwort zurückzusetzen.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Die Datei kann nicht in den angegebenen Pfad :filePath hochgeladen werden. Stellen Sie sicher, dass dieser Ordner auf dem Server beschreibbar ist.', diff --git a/lang/de_informal/errors.php b/lang/de_informal/errors.php index f40b3e148..2ae27c106 100644 --- a/lang/de_informal/errors.php +++ b/lang/de_informal/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Treiber für Social-Media-Konten nicht gefunden', 'social_driver_not_configured' => 'Dein :socialAccount-Konto ist nicht korrekt konfiguriert.', 'invite_token_expired' => 'Dieser Einladungslink ist abgelaufen. Du kannst stattdessen versuchen, dein Passwort zurückzusetzen.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Die Datei kann nicht in den angegebenen Pfad :filePath hochgeladen werden. Stelle sicher, dass dieser Ordner auf dem Server beschreibbar ist.', diff --git a/lang/de_informal/settings.php b/lang/de_informal/settings.php index 4398edebd..e80c2e7b0 100644 --- a/lang/de_informal/settings.php +++ b/lang/de_informal/settings.php @@ -279,7 +279,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung // Licensing 'licenses' => 'Lizenzen', - 'licenses_desc' => 'Diese Seite beschreibt Lizenzinformationen für BookStack zusätzlich zu den Projekten und Bibliotheken, die in BookStack verwendet werden. Viele aufgelistete Projekte dürfen nur in einem Entwicklungskontext verwendet werden.', + 'licenses_desc' => 'Diese Seite beschreibt Lizenzinformationen für BookStack zusätzlich zu den Projekten und Bibliotheken, die in BookStack verwendet werden. Viele aufgelistete Projekte werden nur in einem Entwicklungskontext verwendet.', 'licenses_bookstack' => 'BookStack-Lizenz', 'licenses_php' => 'PHP-Bibliothekslizenzen', 'licenses_js' => 'JavaScript-Bibliothekslizenzen', diff --git a/lang/el/errors.php b/lang/el/errors.php index 93b8dd45a..287240266 100644 --- a/lang/el/errors.php +++ b/lang/el/errors.php @@ -37,6 +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.', // System 'path_not_writable' => 'Η διαδρομή αρχείου :filePath δεν μπόρεσε να μεταφορτωθεί. Βεβαιωθείτε ότι είναι εγγράψιμη στο διακομιστή.', diff --git a/lang/es/errors.php b/lang/es/errors.php index 1bf7db132..97c376df1 100644 --- a/lang/es/errors.php +++ b/lang/es/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Driver social no encontrado', 'social_driver_not_configured' => 'Su configuración :socialAccount no es correcta.', 'invite_token_expired' => 'Este enlace de invitación ha expirado. Puede resetear la contraseña de su cuenta como alternativa.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'El fichero no pudo ser subido a la ruta :filePath . Asegúrese de que es escribible por el servidor.', diff --git a/lang/es_AR/activities.php b/lang/es_AR/activities.php index f0afe2d43..62d986cea 100644 --- a/lang/es_AR/activities.php +++ b/lang/es_AR/activities.php @@ -97,7 +97,7 @@ return [ 'api_token_create_notification' => 'Token de API creado correctamente', 'api_token_update' => 'token de API actualizado', 'api_token_update_notification' => 'Token de API actualizado correctamente', - 'api_token_delete' => 'token de API borrado', + 'api_token_delete' => 'API token eliminado', 'api_token_delete_notification' => 'Token de API eliminado correctamente', // Roles @@ -115,9 +115,9 @@ return [ // Comments 'commented_on' => 'comentado', - 'comment_create' => 'comentario añadido', + 'comment_create' => 'comentario agregado', 'comment_update' => 'comentario actualizado', - 'comment_delete' => 'comentario borrado', + 'comment_delete' => 'comentario eliminado', // Other 'permissions_update' => 'permisos actualizados', diff --git a/lang/es_AR/common.php b/lang/es_AR/common.php index 73a266404..bbda086ac 100644 --- a/lang/es_AR/common.php +++ b/lang/es_AR/common.php @@ -12,7 +12,7 @@ return [ 'save' => 'Guardar', 'continue' => 'Continuar', 'select' => 'Seleccionar', - 'toggle_all' => 'Alternar todo', + 'toggle_all' => 'Mostrar/Ocultar Todo', 'more' => 'Más', // Form Labels @@ -20,7 +20,7 @@ return [ 'description' => 'Descripción', 'role' => 'Rol', 'cover_image' => 'Imagen de cubierta', - 'cover_image_description' => 'Esta imagen debe ser de aproximadamente 440x250px aunque será escalada y recortada para adaptarse a la interfaz de usuario en diferentes escenarios según sea necesario, por lo que las dimensiones en pantalla diferirán.', + 'cover_image_description' => 'Esta imagen debe ser de 440x250px aproximadamente, aunque será escalada y recortada para adaptarse a la interfaz de usuario en los diferentes escenarios según sea necesario, por lo que las dimensiones en pantalla serán diferentes.', // Actions 'actions' => 'Acciones', @@ -42,7 +42,7 @@ return [ 'remove' => 'Remover', 'add' => 'Agregar', 'configure' => 'Configurar', - 'manage' => 'Gestionar', + 'manage' => 'Administra', 'fullscreen' => 'Pantalla completa', 'favourite' => 'Favoritos', 'unfavourite' => 'Eliminar de favoritos', @@ -70,8 +70,8 @@ return [ 'no_items' => 'No hay elementos disponibles', 'back_to_top' => 'Volver arriba', 'skip_to_main_content' => 'Ir al contenido principal', - 'toggle_details' => 'Alternar detalles', - 'toggle_thumbnails' => 'Alternar miniaturas', + 'toggle_details' => 'Mostrar/Ocultar Detalles', + 'toggle_thumbnails' => 'Mostrar/Ocultar Miniaturas', 'details' => 'Detalles', 'grid_view' => 'Vista de grilla', 'list_view' => 'Vista de lista', diff --git a/lang/es_AR/components.php b/lang/es_AR/components.php index d701c857a..0e2c4c88b 100644 --- a/lang/es_AR/components.php +++ b/lang/es_AR/components.php @@ -34,7 +34,7 @@ return [ 'image_delete_success' => 'Imagen borrada exitosamente', 'image_replace' => 'Reemplazar imagen', 'image_replace_success' => 'Imagen actualizada correctamente', - 'image_rebuild_thumbs' => 'Regenerar distintos tamaños', + 'image_rebuild_thumbs' => 'Regenerar Variaciones de Tamaño', 'image_rebuild_thumbs_success' => '¡Imágenes de distinto tamaño regeneradas correctamente!', // Code Editor diff --git a/lang/es_AR/editor.php b/lang/es_AR/editor.php index 52563e4bc..3cd7d4657 100644 --- a/lang/es_AR/editor.php +++ b/lang/es_AR/editor.php @@ -81,9 +81,9 @@ return [ 'table_properties' => 'Propiedades de tabla', 'table_properties_title' => 'Propiedades de Tabla', 'delete_table' => 'Eliminar tabla', - 'table_clear_formatting' => 'Limpiar formato de tabla', + 'table_clear_formatting' => 'Limpiar el formato de tabla', 'resize_to_contents' => 'Redimensionar al contenido', - 'row_header' => 'Fila de cabecera', + 'row_header' => 'Cabecera de fila', 'insert_row_before' => 'Insertar fila arriba', 'insert_row_after' => 'Insertar fila abajo', 'delete_row' => 'Eliminar fila', diff --git a/lang/es_AR/errors.php b/lang/es_AR/errors.php index 922bcd1db..818dccfb7 100644 --- a/lang/es_AR/errors.php +++ b/lang/es_AR/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Driver social no encontrado', 'social_driver_not_configured' => 'Su configuración :socialAccount no es correcta.', 'invite_token_expired' => 'El enace de la esta invitación expiró. Puede intentar restablecer la contraseña de su cuenta', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'La ruta :filePath no pudo ser cargada. Asegurese de que es escribible por el servidor.', diff --git a/lang/et/errors.php b/lang/et/errors.php index 986822726..9cda62521 100644 --- a/lang/et/errors.php +++ b/lang/et/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Sotsiaalmeedia kontode draiverit ei leitud', 'social_driver_not_configured' => 'Sinu :socialAccount konto seaded ei ole korrektsed.', 'invite_token_expired' => 'Link on aegunud. Võid selle asemel proovida oma konto parooli lähtestada.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Faili asukohaga :filePath ei õnnestunud üles laadida. Veendu, et serveril on kirjutusõigused.', diff --git a/lang/eu/errors.php b/lang/eu/errors.php index 61d50d8b1..b5eef6ff2 100644 --- a/lang/eu/errors.php +++ b/lang/eu/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Social driver not found', 'social_driver_not_configured' => 'Your :socialAccount social settings are not configured correctly.', 'invite_token_expired' => 'This invitation link has expired. You can instead try to reset your account password.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'File path :filePath could not be uploaded to. Ensure it is writable to the server.', diff --git a/lang/fa/errors.php b/lang/fa/errors.php index 97c631edc..8c16396b3 100644 --- a/lang/fa/errors.php +++ b/lang/fa/errors.php @@ -37,6 +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.', // System 'path_not_writable' => 'مسیر فایل :filePath را نمی توان در آن آپلود کرد. مطمئن شوید که روی سرور قابل نوشتن است.', diff --git a/lang/fi/errors.php b/lang/fi/errors.php index ec348f0f2..73dc39466 100644 --- a/lang/fi/errors.php +++ b/lang/fi/errors.php @@ -38,6 +38,7 @@ Sovellus ei tunnista ulkoisen todennuspalvelun pyyntöä. Ongelman voi aiheuttaa 'social_driver_not_found' => 'Sosiaalisen median tilin ajuria ei löytynyt', 'social_driver_not_configured' => ':socialAccount-tilin asetuksia ei ole määritetty oikein.', 'invite_token_expired' => 'Tämä kutsulinkki on vanhentunut. Voit sen sijaan yrittää palauttaa tilisi salasanan.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Tiedostopolkuun :filePath ei voitu ladata tiedostoa. Tarkista polun kirjoitusoikeudet.', diff --git a/lang/fr/errors.php b/lang/fr/errors.php index c71ef501d..7d45c09d8 100644 --- a/lang/fr/errors.php +++ b/lang/fr/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Pilote de compte de réseaux sociaux absent', 'social_driver_not_configured' => 'Vos préférences pour le compte :socialAccount sont incorrectes.', 'invite_token_expired' => 'Le lien de cette invitation a expiré. Vous pouvez essayer de réinitialiser votre mot de passe.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Impossible d\'écrire dans :filePath. Assurez-vous d\'avoir les droits d\'écriture sur le serveur', diff --git a/lang/fr/settings.php b/lang/fr/settings.php index fa7433c48..f5c2c6d2b 100644 --- a/lang/fr/settings.php +++ b/lang/fr/settings.php @@ -222,7 +222,7 @@ return [ 'users_api_tokens_desc' => 'Créer et gérer les jetons d\'accès utilisés pour s\'authentifier avec l\'API REST de BookStack. Les permissions pour l\'API sont gérées par l\'utilisateur auquel le jeton appartient.', 'users_api_tokens_none' => 'Aucun jeton API n\'a été créé pour cet utilisateur', 'users_api_tokens_create' => 'Créer un jeton', - 'users_api_tokens_expires' => 'Expiré', + 'users_api_tokens_expires' => 'Expire', 'users_api_tokens_docs' => 'Documentation de l\'API', 'users_mfa' => 'Authentification multi-facteurs', 'users_mfa_desc' => 'Configurer l\'authentification multi-facteurs ajoute une couche supplémentaire de sécurité à votre compte utilisateur.', diff --git a/lang/he/activities.php b/lang/he/activities.php index d8fb69d61..4eadd4196 100644 --- a/lang/he/activities.php +++ b/lang/he/activities.php @@ -6,13 +6,13 @@ return [ // Pages - 'page_create' => 'דף נוצר', + 'page_create' => 'הדף נוצר', 'page_create_notification' => 'הדף נוצר בהצלחה', - 'page_update' => 'דף עודכן', + 'page_update' => 'הדף עודכן', 'page_update_notification' => 'הדף עודכן בהצלחה', - 'page_delete' => 'דף נמחק', + 'page_delete' => 'הדף נמחק', 'page_delete_notification' => 'הדף הוסר בהצלחה', - 'page_restore' => 'דף שוחזר', + 'page_restore' => 'הדף שוחזר', 'page_restore_notification' => 'הדף שוחזר בהצלחה', 'page_move' => 'דף הועבר', 'page_move_notification' => 'Page successfully moved', diff --git a/lang/he/errors.php b/lang/he/errors.php index c82462798..af181b5a5 100644 --- a/lang/he/errors.php +++ b/lang/he/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => '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.', // System 'path_not_writable' => 'לא ניתן להעלות את :filePath אנא ודא שניתן לכתוב למיקום זה', diff --git a/lang/hr/errors.php b/lang/hr/errors.php index 5be97feb9..8c1aad79f 100644 --- a/lang/hr/errors.php +++ b/lang/hr/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Nije pronađeno', 'social_driver_not_configured' => 'Postavke vašeg :socialAccount računa nisu ispravno postavljene.', 'invite_token_expired' => 'Vaša pozivnica je istekla. Pokušajte ponovno postaviti lozinku.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Datoteka :filePath ne može se prenijeti. Učinite je lakše prepoznatljivom vašem serveru.', diff --git a/lang/hu/common.php b/lang/hu/common.php index a79ee00e5..715d5e71c 100644 --- a/lang/hu/common.php +++ b/lang/hu/common.php @@ -20,7 +20,7 @@ return [ 'description' => 'Leírás', 'role' => 'Szerepkör', 'cover_image' => 'Borítókép', - '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' => 'Ennek a képnek körülbelül 440 x 250 képpont méretűnek kell lennie, bár rugalmasan méretezhető és levágható, hogy a felhasználói felülethez illeszkedjen a különböző lehetőségek esetén, így a megjelenítés tényleges méretei eltérőek lesznek.', // Actions 'actions' => 'Műveletek', diff --git a/lang/hu/errors.php b/lang/hu/errors.php index 0183cd192..34e4f2b74 100644 --- a/lang/hu/errors.php +++ b/lang/hu/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Közösségi meghajtó nem található', 'social_driver_not_configured' => ':socialAccount közösségi beállítások nem megfelelőek.', 'invite_token_expired' => 'Ez a meghívó hivatkozás lejárt. Helyette meg lehet próbálni új jelszót megadni a fiókhoz.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => ':filePath elérési út nem tölthető fel. Ellenőrizni kell, hogy az útvonal a kiszolgáló számára írható.', diff --git a/lang/hu/preferences.php b/lang/hu/preferences.php index 11d145064..8c78a1d0e 100644 --- a/lang/hu/preferences.php +++ b/lang/hu/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Beállítások mentése', 'notifications_update_success' => 'Az értesítési beállítások frissítve lettek!', 'notifications_watched' => 'Megfigyelt és figyelmen kívül hagyott elemek', - 'notifications_watched_desc' => 'Az alábbi elemekre egyedi figyelési beállítások vannak alkalmazva. A beállítások frissítéséhez tekintsd meg az elemet, majd keress a figyelési lehetőségeket az oldalsávban.', + 'notifications_watched_desc' => 'Az alábbi elemekre egyedi figyelési beállítások vannak alkalmazva. A beállítások frissítéséhez tekintsd meg az elemet, majd keresd a figyelési lehetőségeket az oldalsávban.', 'auth' => 'Hozzáférés és Biztonság', 'auth_change_password' => 'Jelszó módosítása', diff --git a/lang/hu/settings.php b/lang/hu/settings.php index 9bf8880d3..bacb466aa 100644 --- a/lang/hu/settings.php +++ b/lang/hu/settings.php @@ -109,7 +109,7 @@ return [ 'recycle_bin_contents_empty' => 'A lomtár jelenleg üres', 'recycle_bin_empty' => 'Lomtár kiürítése', 'recycle_bin_empty_confirm' => 'Ezzel véglegesen megsemmisíti a lomtárban lévő összes elemet, beleértve az egyes tételekben található tartalmat is. Biztos benne, hogy ki akarja üríteni a lomtárat?', - 'recycle_bin_destroy_confirm' => 'This action will permanently delete this item from the system, along with any child elements listed below, and you will not be able to restore this content. Are you sure you want to permanently delete this item?', + 'recycle_bin_destroy_confirm' => 'Ez a művelet véglegesen törli ezt az elemet a rendszerből az alább felsorolt összes alárendelt elemmel együtt, és nem fogja tudni visszaállítani ezt a tartalmat. Biztosan véglegesen törli ezt az elemet?', 'recycle_bin_destroy_list' => 'Megsemmisítendő elemek', 'recycle_bin_restore_list' => 'Visszaállítandó elemek', 'recycle_bin_restore_confirm' => 'Ez a művelet visszaállítja a törölt elemet, beleértve az utódelemeket is, az eredeti helyükre. Ha az eredeti helyet azóta törölték, és most a lomtárban van, akkor a szülőelemet is vissza kell állítani.', @@ -277,13 +277,13 @@ return [ 'webhooks_last_error_message' => 'Utolsó hibaüzenet:', // Licensing - 'licenses' => 'Licenses', - 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', - 'licenses_bookstack' => 'BookStack License', - 'licenses_php' => 'PHP Library Licenses', - 'licenses_js' => 'JavaScript Library Licenses', - 'licenses_other' => 'Other Licenses', - 'license_details' => 'License Details', + 'licenses' => 'Licenszek', + 'licenses_desc' => 'Ez az oldal a BookStack licencinformációit részletezi, a BookStackben használt projekteken és könyvtárakon kívül. Sok felsorolt projekt csak fejlesztési környezetben használható.', + 'licenses_bookstack' => 'BookStack Licensz', + 'licenses_php' => 'PHP könyvtár licencek', + 'licenses_js' => 'JavaScript könyvtár licencek', + 'licenses_other' => 'Egyéb licencek', + 'license_details' => 'Licenc részletek', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/id/errors.php b/lang/id/errors.php index 64ac14639..de3883580 100644 --- a/lang/id/errors.php +++ b/lang/id/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Pengemudi sosial tidak ditemukan', 'social_driver_not_configured' => 'Pengaturan sosial :socialAccount Anda tidak dikonfigurasi dengan benar.', 'invite_token_expired' => 'Tautan undangan ini telah kedaluwarsa. Sebagai gantinya, Anda dapat mencoba mengatur ulang kata sandi akun Anda.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Jalur berkas :filePath tidak dapat diunggah. Pastikan berkas tersebut dapat ditulis ke server.', diff --git a/lang/it/errors.php b/lang/it/errors.php index 05bf5373f..a65ea5e87 100644 --- a/lang/it/errors.php +++ b/lang/it/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Driver social non trovato', 'social_driver_not_configured' => 'Le impostazioni di :socialAccount non sono configurate correttamente.', 'invite_token_expired' => 'Il link di invito è scaduto. Puoi provare a resettare la password del tuo account.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Il percorso :filePath non è scrivibile. Controlla che abbia i permessi corretti.', diff --git a/lang/ja/errors.php b/lang/ja/errors.php index a754f61c0..a94454111 100644 --- a/lang/ja/errors.php +++ b/lang/ja/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Social driverが見つかりません', 'social_driver_not_configured' => 'あなたの:socialAccount設定は正しく構成されていません。', 'invite_token_expired' => 'この招待リンクの有効期限が切れています。 代わりにアカウントのパスワードをリセットしてみてください。', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'ファイルパス :filePath へアップロードできませんでした。サーバ上での書き込みが許可されているか確認してください。', diff --git a/lang/ka/errors.php b/lang/ka/errors.php index 8773a78cb..752eb5672 100644 --- a/lang/ka/errors.php +++ b/lang/ka/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Social driver not found', 'social_driver_not_configured' => 'Your :socialAccount social settings are not configured correctly.', 'invite_token_expired' => 'This invitation link has expired. You can instead try to reset your account password.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'File path :filePath could not be uploaded to. Ensure it is writable to the server.', diff --git a/lang/ko/errors.php b/lang/ko/errors.php index 4e076c007..bcfdf876c 100644 --- a/lang/ko/errors.php +++ b/lang/ko/errors.php @@ -37,6 +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.', // System 'path_not_writable' => '파일 경로 :filePath 에 업로드할 수 없습니다. 서버에 저장이 가능한지 확인하세요.', diff --git a/lang/lt/errors.php b/lang/lt/errors.php index cde76b056..c7ecf8245 100644 --- a/lang/lt/errors.php +++ b/lang/lt/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Socialinis diskas nerastas', 'social_driver_not_configured' => 'Jūsų :socialAccount socaliniai nustatymai sukonfigūruoti neteisingai.', 'invite_token_expired' => 'Ši kvietimo nuoroda baigė galioti. Vietoj to, jūs galite bandyti iš naujo nustatyti savo paskyros slaptažodį.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Į failo kelią :filePath negalima įkelti. Įsitikinkite, kad jis yra įrašomas į serverį.', diff --git a/lang/lv/errors.php b/lang/lv/errors.php index 27b77b631..22ccbe383 100644 --- a/lang/lv/errors.php +++ b/lang/lv/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Sociālā tīkla savienojums nav atrasts', 'social_driver_not_configured' => 'Jūsu :socialAccount sociālie iestatījumi nav uzstādīti pareizi.', 'invite_token_expired' => 'Šī uzaicinājuma saite ir novecojusi. Tā vietā jūs varat mēģināt atiestatīt sava konta paroli.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Faila ceļā :filePath nav iespējams ielādēt failus. Lūdzu pārliecinieties, ka serverim tur ir rakstīšanas tiesības.', diff --git a/lang/nb/errors.php b/lang/nb/errors.php index 1e776be80..2f3e802ba 100644 --- a/lang/nb/errors.php +++ b/lang/nb/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Autentiseringstjeneste fra sosiale medier er ikke installert', 'social_driver_not_configured' => 'Dine :socialAccount innstilliner er ikke angitt.', 'invite_token_expired' => 'Invitasjonslenken har utgått, du kan forsøke å be om nytt passord istede.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Filstien :filePath aksepterer ikke filer, du må sjekke filstitilganger i systemet.', diff --git a/lang/nl/activities.php b/lang/nl/activities.php index 1223dcf34..08c168e9f 100644 --- a/lang/nl/activities.php +++ b/lang/nl/activities.php @@ -52,7 +52,7 @@ return [ // Revisions 'revision_restore' => 'herstelde revisie', 'revision_delete' => 'verwijderde revisie', - 'revision_delete_notification' => 'Revisie met succes verwijderd', + 'revision_delete_notification' => 'Revisie succesvol verwijderd', // Favourites 'favourite_add_notification' => '":name" is toegevoegd aan je favorieten', @@ -66,14 +66,14 @@ return [ 'auth_register' => 'registreerde als nieuwe gebruiker', 'auth_password_reset_request' => 'vraagde een nieuw gebruikerswachtwoord aan', 'auth_password_reset_update' => 'stelde gebruikerswachtwoord opnieuw in', - 'mfa_setup_method' => 'heeft zijn meervoudige verificatie methode ingesteld', + 'mfa_setup_method' => 'stelde meervoudige verificatie methode in', 'mfa_setup_method_notification' => 'Meervoudige verificatie methode succesvol geconfigureerd', - 'mfa_remove_method' => 'heeft zijn meervoudige verificatie methode verwijderd', + 'mfa_remove_method' => 'verwijderde meervoudige verificatie methode', 'mfa_remove_method_notification' => 'Meervoudige verificatie methode is succesvol verwijderd', // Settings 'settings_update' => 'werkte instellingen bij', - 'settings_update_notification' => 'Instellingen met succes bijgewerkt', + 'settings_update_notification' => 'Instellingen succesvol bijgewerkt', 'maintenance_action_run' => 'voerde onderhoudsactie uit', // Webhooks @@ -86,7 +86,7 @@ return [ // Users 'user_create' => 'maakte gebruiker aan', - 'user_create_notification' => 'Gebruiker met succes aangemaakt', + 'user_create_notification' => 'Gebruiker succesvol aangemaakt', 'user_update' => 'werkte gebruiker bij', 'user_update_notification' => 'Gebruiker succesvol bijgewerkt', 'user_delete' => 'verwijderde gebruiker', @@ -95,9 +95,9 @@ return [ // API Tokens 'api_token_create' => 'API-token aangemaakt', 'api_token_create_notification' => 'API-token met succes aangemaakt', - 'api_token_update' => 'geüpdatet API-token', + 'api_token_update' => 'wijzigde API-token', 'api_token_update_notification' => 'API-token met succes bijgewerkt', - 'api_token_delete' => 'verwijderd API-token', + 'api_token_delete' => 'verwijderde API-token', 'api_token_delete_notification' => 'API-token met succes verwijderd', // Roles diff --git a/lang/nl/auth.php b/lang/nl/auth.php index a0dc79ab1..e3ff59cd6 100644 --- a/lang/nl/auth.php +++ b/lang/nl/auth.php @@ -36,15 +36,15 @@ return [ 'register_confirm' => 'Controleer je e-mail en klik op de bevestigingsknop om toegang te krijgen tot :appName.', 'registrations_disabled' => 'Registratie is momenteel niet mogelijk', 'registration_email_domain_invalid' => 'Dit e-maildomein wordt niet toegelaten tot deze applicatie', - 'register_success' => 'Bedankt voor het aanmelden! Je bent nu geregistreerd en aangemeld.', + 'register_success' => 'Bedankt voor het aanmelden! Je bent nu geregistreerd en ingelogd.', // Login auto-initiation - 'auto_init_starting' => 'Poging tot inloggen', - 'auto_init_starting_desc' => 'We maken contact met jouw authenticatiesysteem om het inlogproces te starten. Als er na 5 seconden geen vooruitgang is, kun je proberen op de onderstaande link te klikken.', + 'auto_init_starting' => 'Proberen in te loggen', + 'auto_init_starting_desc' => 'We maken contact met je authenticatiesysteem om het inlogproces te starten. Als er na 5 seconden geen vooruitgang is, kun je proberen op de onderstaande link te klikken.', 'auto_init_start_link' => 'Ga verder met authenticatie', // Password Reset - 'reset_password' => 'Wachtwoord herstellen', + 'reset_password' => 'Wachtwoord Herstellen', 'reset_password_send_instructions' => 'Geef je e-mailadres op en er wordt een link gestuurd om je wachtwoord te herstellen.', 'reset_password_send_button' => 'Stuur Herstel Link', 'reset_password_sent' => 'Een link om het wachtwoord te resetten zal verstuurd worden naar :email als dat e-mailadres in het systeem gevonden is.', @@ -62,7 +62,7 @@ return [ 'email_confirm_success' => 'Je e-mailadres is bevestigd! Je zou nu moeten kunnen inloggen met dit e-mailadres.', 'email_confirm_resent' => 'Bevestigingsmail opnieuw verzonden, controleer je inbox.', 'email_confirm_thanks' => 'Bedankt voor de bevestiging!', - 'email_confirm_thanks_desc' => 'Wacht even terwijl jouw bevestiging wordt behandeld. Als je na 3 seconden niet wordt doorverwezen, druk dan op de onderstaande link "Doorgaan" om verder te gaan.', + 'email_confirm_thanks_desc' => 'Wacht even terwijl je bevestiging wordt behandeld. Als je na 3 seconden niet wordt doorverwezen, druk dan op de onderstaande link "Doorgaan" om verder te gaan.', 'email_not_confirmed' => 'E-mailadres nog niet bevestigd', 'email_not_confirmed_text' => 'Je e-mailadres is nog niet bevestigd.', @@ -76,20 +76,20 @@ return [ 'user_invite_email_text' => 'Klik op de onderstaande knop om een account wachtwoord in te stellen en toegang te krijgen:', 'user_invite_email_action' => 'Account wachtwoord instellen', 'user_invite_page_welcome' => 'Welkom bij :appName!', - 'user_invite_page_text' => 'Om je account af te ronden en toegang te krijgen moet je een wachtwoord instellen dat gebruikt wordt om in te loggen op :appName bij toekomstige bezoeken.', - 'user_invite_page_confirm_button' => 'Bevestig wachtwoord', + 'user_invite_page_text' => 'Om je registratie af te ronden en toegang te krijgen moet je een wachtwoord instellen dat gebruikt zal worden om in te loggen op :appName bij toekomstige bezoeken.', + 'user_invite_page_confirm_button' => 'Wachtwoord Bevestigen', 'user_invite_success_login' => 'Wachtwoord ingesteld, je zou nu moeten kunnen inloggen met je ingestelde wachtwoord om toegang te krijgen tot :appName!', // Multi-factor Authentication - 'mfa_setup' => 'Multi-factor authenticatie instellen', - 'mfa_setup_desc' => 'Stel multi-factor authenticatie in als een extra beveiligingslaag voor je gebruikersaccount.', - 'mfa_setup_configured' => 'Reeds geconfigureerd', + 'mfa_setup' => 'Meervoudige verificatie instellen', + 'mfa_setup_desc' => 'Stel meervoudige verificatie in als een extra beveiligingslaag voor je gebruikersaccount.', + 'mfa_setup_configured' => 'Is al geconfigureerd', 'mfa_setup_reconfigure' => 'Herconfigureren', 'mfa_setup_remove_confirmation' => 'Weet je zeker dat je deze multi-factor authenticatie methode wilt verwijderen?', 'mfa_setup_action' => 'Instellen', 'mfa_backup_codes_usage_limit_warning' => 'Je hebt minder dan 5 back-upcodes over. Genereer en sla een nieuwe set op voordat je geen codes meer hebt om te voorkomen dat je buiten je account wordt gesloten.', 'mfa_option_totp_title' => 'Mobiele app', - 'mfa_option_totp_desc' => 'Om multi-factor authenticatie te gebruiken heb je een mobiele applicatie nodig die TOTP ondersteunt, zoals Google Authenticator, Authy of Microsoft Authenticator.', + 'mfa_option_totp_desc' => 'Om meervoudige verificatie te gebruiken heb je een mobiele applicatie nodig die TOTP ondersteunt, zoals Google Authenticator, Authy of Microsoft Authenticator.', 'mfa_option_backup_codes_title' => 'Back-up Codes', 'mfa_option_backup_codes_desc' => 'Bewaar veilig een set eenmalige back-upcodes die je kunt invoeren om je identiteit te verifiëren.', 'mfa_gen_confirm_and_enable' => 'Bevestigen en inschakelen', @@ -98,13 +98,13 @@ return [ 'mfa_gen_backup_codes_download' => 'Download Codes', 'mfa_gen_backup_codes_usage_warning' => 'Elke code kan slechts eenmaal gebruikt worden', 'mfa_gen_totp_title' => 'Mobiele app installatie', - 'mfa_gen_totp_desc' => 'Om multi-factor authenticatie te gebruiken heb je een mobiele applicatie nodig die TOTP ondersteunt, zoals Google Authenticator, Authy of Microsoft Authenticator.', + 'mfa_gen_totp_desc' => 'Om meervoudige verificatie te gebruiken heb je een mobiele applicatie nodig die TOTP ondersteunt, zoals Google Authenticator, Authy of Microsoft Authenticator.', 'mfa_gen_totp_scan' => 'Scan de onderstaande QR-code door gebruik te maken van je favoriete authenticatie-app om aan de slag te gaan.', 'mfa_gen_totp_verify_setup' => 'Installatie verifiëren', 'mfa_gen_totp_verify_setup_desc' => 'Controleer of alles werkt door het invoeren van een code, die wordt gegenereerd binnen je authenticatie-app, in het onderstaande invoerveld:', 'mfa_gen_totp_provide_code_here' => 'Vul je app-gegenereerde code hier in', 'mfa_verify_access' => 'Verifieer toegang', - 'mfa_verify_access_desc' => 'Je moet jouw identiteit bevestigen via een extra verificatieniveau voordat je toegang krijgt tot je gebruikersaccount. Verifieer met een van de door u geconfigureerde methoden om verder te gaan.', + 'mfa_verify_access_desc' => 'Je moet je identiteit bevestigen via een extra verificatieniveau voordat je toegang krijgt tot je gebruikersaccount. Verifieer met een van de door jou geconfigureerde methoden om verder te gaan.', 'mfa_verify_no_methods' => 'Geen methode geconfigureerd', 'mfa_verify_no_methods_desc' => 'Er konden geen meervoudige verificatie methoden voor je account gevonden worden. Je zult minstens één methode moeten instellen voordat je toegang krijgt.', 'mfa_verify_use_totp' => 'Verifieer met een mobiele app', diff --git a/lang/nl/editor.php b/lang/nl/editor.php index 481f99ded..89b2e7bea 100644 --- a/lang/nl/editor.php +++ b/lang/nl/editor.php @@ -143,7 +143,7 @@ return [ 'source' => 'Bron', 'alt_desc' => 'Alternatieve beschrijving', 'embed' => 'Insluiten', - 'paste_embed' => 'Plak jouw insluitcode hieronder:', + 'paste_embed' => 'Plak je insluitcode hieronder:', 'url' => 'URL', 'text_to_display' => 'Weer te geven tekst', 'title' => 'Titel', diff --git a/lang/nl/entities.php b/lang/nl/entities.php index 23e5c9750..69cefd233 100644 --- a/lang/nl/entities.php +++ b/lang/nl/entities.php @@ -91,8 +91,8 @@ return [ 'shelves_popular' => 'Populaire boekenplanken', 'shelves_new' => 'Nieuwe boekenplanken', 'shelves_new_action' => 'Nieuwe boekenplank', - 'shelves_popular_empty' => 'De meest populaire boekenplanken worden hier weergegeven.', - 'shelves_new_empty' => 'De meest recent gemaakte boekenplanken worden hier weergeven.', + 'shelves_popular_empty' => 'Hier worden de meest populaire boekenplanken weergegeven.', + 'shelves_new_empty' => 'Hier worden de meest recent gemaakte boekenplanken weergegeven.', 'shelves_save' => 'Boekenplank opslaan', 'shelves_books' => 'Boeken op deze plank', 'shelves_add_books' => 'Voeg boeken toe aan deze plank', @@ -124,8 +124,8 @@ return [ 'books_recent' => 'Recente boeken', 'books_new' => 'Nieuwe boeken', 'books_new_action' => 'Nieuw boek', - 'books_popular_empty' => 'De meest populaire boeken worden hier weergegeven.', - 'books_new_empty' => 'De meest recent gemaakte boeken verschijnen hier.', + 'books_popular_empty' => 'Hier worden de meest populaire boeken weergegeven.', + 'books_new_empty' => 'Hier worden de meest recent gemaakte boeken weergegeven.', 'books_create' => 'Nieuw boek maken', 'books_delete' => 'Boek verwijderen', 'books_delete_named' => 'Verwijder boek :bookName', @@ -309,7 +309,7 @@ return [ 'tags_index_desc' => 'Labels kunnen worden toegepast op inhoud binnen het systeem om een flexibele vorm van categorisering toe te passen. Labels kunnen zowel een sleutel als een waarde hebben, waarbij de waarde optioneel is. Eenmaal toegepast, kan de inhoud worden opgevraagd aan de hand van de naam en de waarde van het label.', 'tag_name' => 'Labelnaam', 'tag_value' => 'Labelwaarde (Optioneel)', - 'tags_explain' => "Voeg enkele labels toe om jouw inhoud beter te categoriseren. \nJe kunt een waarde aan een label toekennen voor een meer gedetailleerde organisatie.", + 'tags_explain' => "Voeg enkele labels toe om je inhoud beter te categoriseren.\nJe kunt een waarde aan een label toekennen voor een meer gedetailleerde organisatie.", 'tags_add' => 'Voeg nog een label toe', 'tags_remove' => 'Verwijder deze label', 'tags_usages' => 'Totaal aantal label-toepassingen', diff --git a/lang/nl/errors.php b/lang/nl/errors.php index 74b14e08d..7f8546625 100644 --- a/lang/nl/errors.php +++ b/lang/nl/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Social driver niet gevonden', 'social_driver_not_configured' => 'Je :socialAccount instellingen zijn niet correct geconfigureerd.', 'invite_token_expired' => 'Deze uitnodigingslink is verlopen. Je kunt in plaats daarvan proberen je wachtwoord opnieuw in te stellen.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Bestandspad :filePath kon niet naar geüpload worden. Zorg dat je schrijfrechten op de server hebt.', diff --git a/lang/nl/settings.php b/lang/nl/settings.php index 828036c1b..a7d6fde9b 100644 --- a/lang/nl/settings.php +++ b/lang/nl/settings.php @@ -95,7 +95,7 @@ return [ 'maint_regen_references' => 'Verwijzingen opnieuw genereren', 'maint_regen_references_desc' => 'Deze actie zal de kruisverwijzingen index binnen de database opnieuw opbouwen. Dit wordt doorgaans automatisch gedaan, maar deze actie kan nuttig zijn om oude inhoud of inhoud die via onofficiële methoden is toegevoegd te indexeren.', 'maint_regen_references_success' => 'Verwijzingen index is opnieuw gegenereerd!', - 'maint_timeout_command_note' => 'Opmerking: Het uitvoeren van deze actie kan enige tijd in beslag nemen, wat in sommige webomgevingen kan leiden tot time-outs. Als alternatief kan deze actie ook worden uitgevoerd met een terminal commando.', + 'maint_timeout_command_note' => 'Let op: Het uitvoeren van deze actie kan enige tijd in beslag nemen, wat in sommige webomgevingen kan leiden tot time-outs. Als alternatief kan deze actie ook worden uitgevoerd met een terminal-commando.', // Recycle Bin 'recycle_bin' => 'Prullenbak', diff --git a/lang/nn/errors.php b/lang/nn/errors.php index 2d9f58b71..be1823db0 100644 --- a/lang/nn/errors.php +++ b/lang/nn/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Autentiseringstjeneste fra sosiale medier er ikke installert', 'social_driver_not_configured' => 'Dine :socialAccount innstilliner er ikke angitt.', 'invite_token_expired' => 'Invitasjonslenken har utgått, du kan forsøke å be om nytt passord istede.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Filstien :filePath aksepterer ikkje filer, du må sjekke filstitilganger i systemet.', diff --git a/lang/pl/errors.php b/lang/pl/errors.php index 8b1ae1608..89e4349a5 100644 --- a/lang/pl/errors.php +++ b/lang/pl/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Funkcja społecznościowa nie została odnaleziona', 'social_driver_not_configured' => 'Ustawienia konta :socialAccount nie są poprawne.', 'invite_token_expired' => 'Zaproszenie wygasło. Możesz spróować zresetować swoje hasło.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Zapis do ścieżki :filePath jest niemożliwy. Upewnij się że aplikacja ma prawa do zapisu plików na serwerze.', diff --git a/lang/pt/errors.php b/lang/pt/errors.php index 67d7bbecf..b695caf96 100644 --- a/lang/pt/errors.php +++ b/lang/pt/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Social driver não encontrado', 'social_driver_not_configured' => 'Os seus parâmetros sociais de :socialAccount não estão corretamente configurados.', 'invite_token_expired' => 'Este link de convite expirou. Alternativamente, pode tentar redefinir a senha da sua conta.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'O caminho do arquivo :filePath não pôde ser carregado. Certifique-se de que tem permissões de escrita no servidor.', diff --git a/lang/pt_BR/errors.php b/lang/pt_BR/errors.php index ca0506867..f57784f9f 100644 --- a/lang/pt_BR/errors.php +++ b/lang/pt_BR/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Social driver não encontrado', 'social_driver_not_configured' => 'Seus parâmetros socials de :socialAccount não estão configurados corretamente.', 'invite_token_expired' => 'Esse link de convite expirou. Alternativamente, você pode tentar redefinir a senha da sua conta.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'O caminho de destino (:filePath) de upload de arquivo não possui permissão de escrita. Certifique-se que ele possui direitos de escrita no servidor.', diff --git a/lang/ro/errors.php b/lang/ro/errors.php index a1ac0e04a..71e994be0 100644 --- a/lang/ro/errors.php +++ b/lang/ro/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Driver social negăsit', 'social_driver_not_configured' => 'Setările tale sociale :socialAccount nu sunt configurate corect.', 'invite_token_expired' => 'Acest link de invitație a expirat. Poți încerca să îți resetezi parola contului.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Calea fișierului :filePath nu a putut fi încărcată. Asigurați-vă că poate fi scrisă pe server.', diff --git a/lang/ru/errors.php b/lang/ru/errors.php index 1fe57af2f..596d8b78a 100644 --- a/lang/ru/errors.php +++ b/lang/ru/errors.php @@ -37,6 +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.', // System 'path_not_writable' => 'Невозможно загрузить файл по пути :filePath. Убедитесь что сервер доступен для записи.', diff --git a/lang/sk/errors.php b/lang/sk/errors.php index e09f5f04e..ae9575ca5 100644 --- a/lang/sk/errors.php +++ b/lang/sk/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Ovládač socialnych sietí nebol nájdený', 'social_driver_not_configured' => 'Nastavenia Vášho :socialAccount účtu nie sú správne.', 'invite_token_expired' => 'Platnosť tohto odkazu na pozvánku vypršala. Namiesto toho sa môžete pokúsiť obnoviť heslo účtu.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Do cesty :filePath sa nedá nahrávať. Uistite sa, že je zapisovateľná serverom.', diff --git a/lang/sl/errors.php b/lang/sl/errors.php index 1dacb6716..6da88f149 100644 --- a/lang/sl/errors.php +++ b/lang/sl/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Socialni vtičnik ni najden', 'social_driver_not_configured' => 'Vaše nastavitve :socialAccount niso pravilo nastavljene.', 'invite_token_expired' => 'Ta povezava je potekla. Namesto tega lahko ponastavite vaše geslo računa.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Poti :filePath ni bilo mogoče naložiti. Prepričajte se, da je zapisljiva na strežnik.', diff --git a/lang/sq/errors.php b/lang/sq/errors.php index 8773a78cb..752eb5672 100644 --- a/lang/sq/errors.php +++ b/lang/sq/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Social driver not found', 'social_driver_not_configured' => 'Your :socialAccount social settings are not configured correctly.', 'invite_token_expired' => 'This invitation link has expired. You can instead try to reset your account password.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'File path :filePath could not be uploaded to. Ensure it is writable to the server.', diff --git a/lang/sr/errors.php b/lang/sr/errors.php index 5f109dc4e..ba0043600 100644 --- a/lang/sr/errors.php +++ b/lang/sr/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Social driver not found', 'social_driver_not_configured' => 'Your :socialAccount social settings are not configured correctly.', 'invite_token_expired' => 'This invitation link has expired. You can instead try to reset your account password.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'File path :filePath could not be uploaded to. Ensure it is writable to the server.', diff --git a/lang/sv/editor.php b/lang/sv/editor.php index 54d55052b..0ada0a4ce 100644 --- a/lang/sv/editor.php +++ b/lang/sv/editor.php @@ -81,9 +81,9 @@ return [ 'table_properties' => 'Tabellegenskaper', 'table_properties_title' => 'Tabellegenskaper', 'delete_table' => 'Ta bort tabell', - 'table_clear_formatting' => 'Clear table formatting', + 'table_clear_formatting' => 'Rensa tabell-formatering', 'resize_to_contents' => 'Resize to contents', - 'row_header' => 'Row header', + 'row_header' => 'Radrubrik', 'insert_row_before' => 'Infoga rad före', 'insert_row_after' => 'Infoga rad efter', 'delete_row' => 'Ta bort rad', @@ -147,11 +147,11 @@ return [ 'url' => 'URL', 'text_to_display' => 'Text som ska visas', 'title' => 'Titel', - 'open_link' => 'Open link', - 'open_link_in' => 'Open link in...', + 'open_link' => 'Öppna länk', + 'open_link_in' => 'Öppna länk i...', 'open_link_current' => 'Aktuellt fönster', 'open_link_new' => 'Nytt fönster', - 'remove_link' => 'Remove link', + 'remove_link' => 'Radera länk', 'insert_collapsible' => 'Infoga hopfällbart block', 'collapsible_unwrap' => 'Expandera', 'edit_label' => 'Redigera etikett', diff --git a/lang/sv/errors.php b/lang/sv/errors.php index 7f44ee713..79147f6c6 100644 --- a/lang/sv/errors.php +++ b/lang/sv/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Drivrutinen för den här tjänsten hittades inte', 'social_driver_not_configured' => 'Dina inställningar för :socialAccount är inte korrekta.', 'invite_token_expired' => 'Denna inbjudningslänk har löpt ut. Du kan istället försöka återställa ditt kontos lösenord.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Kunde inte ladda upp till sökvägen :filePath. Kontrollera att webbservern har skrivåtkomst.', diff --git a/lang/sv/settings.php b/lang/sv/settings.php index 3ce6567b0..5b5738f79 100644 --- a/lang/sv/settings.php +++ b/lang/sv/settings.php @@ -32,7 +32,7 @@ return [ 'app_custom_html_desc' => 'Innehåll i det här fältet placeras längst ner i -sektionen på varje sida. Detta kan användas för att skriva över stilmallar eller lägga in spårningskoder.', 'app_custom_html_disabled_notice' => 'Anpassat innehåll i HTML-huvudet är inaktiverat på denna inställningssida för att säkerställa att eventuella ändringar som påverkar funktionaliteten kan återställas.', 'app_logo' => 'Applikationslogotyp', - 'app_logo_desc' => 'This is used in the application header bar, among other areas. This image should be 86px in height. Large images will be scaled down.', + 'app_logo_desc' => 'Detta används bland annat i applikationshuvudet. Bilden bör vara 86 pixlar i höjd. Stora bilder skalas ned.', 'app_icon' => 'Application Icon', 'app_icon_desc' => 'This icon is used for browser tabs and shortcut icons. This should be a 256px square PNG image.', 'app_homepage' => 'Startsida', @@ -48,11 +48,11 @@ return [ 'app_disable_comments_desc' => 'Inaktivera kommentarer på alla sidor i applikationen. Befintliga kommentarer visas inte.', // Color settings - 'color_scheme' => 'Application Color Scheme', - 'color_scheme_desc' => 'Set the colors to use in the application user interface. Colors can be configured separately for dark and light modes to best fit the theme and ensure legibility.', - 'ui_colors_desc' => 'Set the application primary color and default link color. The primary color is mainly used for the header banner, buttons and interface decorations. The default link color is used for text-based links and actions, both within written content and in the application interface.', - 'app_color' => 'Primary Color', - 'link_color' => 'Default Link Color', + 'color_scheme' => 'Programmets färgschema', + 'color_scheme_desc' => 'Ställ in de färger som ska användas i applikationens användargränssnitt. Färger kan konfigureras separat för mörka och ljusa lägen för att bäst passa temat och säkerställa läsbarhet.', + 'ui_colors_desc' => 'Ange applikationens primära färg och standard färg för länkar. Den primära färgen används främst för huvudrubriken, knappar och gränssnitt dekorationer. Standardfärgen på länken används för textbaserade länkar och åtgärder, både inom skriftligt innehåll och i applikationsgränssnittet.', + 'app_color' => 'Primärfärg', + 'link_color' => 'Standardfärg för länkar', 'content_colors_desc' => 'Set colors for all elements in the page organisation hierarchy. Choosing colors with a similar brightness to the default colors is recommended for readability.', 'bookshelf_color' => 'Hyllfärg', 'book_color' => 'Bokfärg', @@ -214,8 +214,8 @@ return [ 'users_social_accounts_info' => 'Här kan du ansluta dina andra konton för snabbare och smidigare inloggning. Om du kopplar från en tjänst här kommer de behörigheter som tidigare givits inte att tas bort - ta bort behörigheter genom att logga in på ditt konto på tjänsten i fråga.', 'users_social_connect' => 'Anslut konto', 'users_social_disconnect' => 'Koppla från konto', - 'users_social_status_connected' => 'Connected', - 'users_social_status_disconnected' => 'Disconnected', + 'users_social_status_connected' => 'Ansluten', + 'users_social_status_disconnected' => 'Bortkopplad', 'users_social_connected' => ':socialAccount har kopplats till ditt konto.', 'users_social_disconnected' => ':socialAccount har kopplats bort från ditt konto.', 'users_api_tokens' => 'API-nyckel', @@ -277,12 +277,12 @@ return [ 'webhooks_last_error_message' => 'Senaste felmeddelande:', // Licensing - 'licenses' => 'Licenses', + 'licenses' => 'Licenser', 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', 'licenses_bookstack' => 'BookStack License', 'licenses_php' => 'PHP Library Licenses', 'licenses_js' => 'JavaScript Library Licenses', - 'licenses_other' => 'Other Licenses', + 'licenses_other' => 'Andra licenser', 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all diff --git a/lang/tr/errors.php b/lang/tr/errors.php index 3e6138c7b..f693a05f3 100644 --- a/lang/tr/errors.php +++ b/lang/tr/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Social driver bulunamadı', 'social_driver_not_configured' => ':socialAccount ayarlarınız doğru bir şekilde ayarlanmadı.', 'invite_token_expired' => 'Davetiye bağlantısının süresi doldu. Bunun yerine parolanızı sıfırlamayı deneyebilirsiniz.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => ':filePath dosya yolu yüklenemedi. Sunucuya yazılabilir olduğundan emin olun.', diff --git a/lang/uk/errors.php b/lang/uk/errors.php index 92d91c183..6320a67cb 100644 --- a/lang/uk/errors.php +++ b/lang/uk/errors.php @@ -37,6 +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.', // System 'path_not_writable' => 'Не вдається завантажити шлях до файлу :filePath. Переконайтеся, що він доступний для запису на сервер.', diff --git a/lang/uz/errors.php b/lang/uz/errors.php index cbd4d630c..d2d8a9c0b 100644 --- a/lang/uz/errors.php +++ b/lang/uz/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Ijtimoiy haydovchi topilmadi', 'social_driver_not_configured' => 'Sizning :socialAccount ijtimoiy sozlamalaringiz toʻgʻri sozlanmagan.', 'invite_token_expired' => 'Bu taklif havolasi muddati tugagan. Buning oʻrniga hisobingiz parolini tiklashga urinib koʻrishingiz mumkin.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Fayl yoʻli :filePath faylini yuklab boʻlmadi. Uning serverga yozilishi mumkinligiga ishonch hosil qiling.', diff --git a/lang/vi/errors.php b/lang/vi/errors.php index 47170b10b..da58c57a9 100644 --- a/lang/vi/errors.php +++ b/lang/vi/errors.php @@ -37,6 +37,7 @@ return [ 'social_driver_not_found' => 'Không tìm thấy driver cho MXH', 'social_driver_not_configured' => 'Cài đặt MXH :socialAccount của bạn đang không được cấu hình hợp lệ.', 'invite_token_expired' => 'Liên kết mời này đã hết hạn. Bạn có thể thử đặt lại mật khẩu của tài khoản.', + 'login_user_not_found' => 'A user for this action could not be found.', // System 'path_not_writable' => 'Đường dẫn tệp tin :filePath không thể tải đến được. Đảm bảo rằng đường dẫn này có thể ghi được ở trên máy chủ.', diff --git a/lang/zh_CN/errors.php b/lang/zh_CN/errors.php index 3627c88d8..0a0318381 100644 --- a/lang/zh_CN/errors.php +++ b/lang/zh_CN/errors.php @@ -37,6 +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.', // System 'path_not_writable' => '无法上传到文件路径“:filePath”,请确保它可写入服务器。', diff --git a/lang/zh_TW/errors.php b/lang/zh_TW/errors.php index 05f7b035c..5b0751353 100644 --- a/lang/zh_TW/errors.php +++ b/lang/zh_TW/errors.php @@ -37,6 +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.', // System 'path_not_writable' => '無法上傳到 :filePath 檔案路徑。請確定其對伺服器來說是可寫入的。', diff --git a/lang/zh_TW/settings.php b/lang/zh_TW/settings.php index 938a1000c..572739f29 100644 --- a/lang/zh_TW/settings.php +++ b/lang/zh_TW/settings.php @@ -136,7 +136,8 @@ return [ // Role Settings 'roles' => '角色', 'role_user_roles' => '使用者角色', - 'roles_index_desc' => 'Roles are used to group users & provide system permission to their members. When a user is a member of multiple roles the privileges granted will stack and the user will inherit all abilities.', + 'roles_index_desc' => '「角色」用於將系統權限套用至使用者群組。當使用者擁有多角色時, +使用者會自動繼承角色中的所有系統權限', 'roles_x_users_assigned' => ':count user assigned|:count users assigned', 'roles_x_permissions_provided' => ':count permission|:count permissions', 'roles_assigned_users' => 'Assigned Users', @@ -277,13 +278,13 @@ return [ 'webhooks_last_error_message' => '上次錯誤信息', // Licensing - 'licenses' => 'Licenses', - 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses' => '授權', + 'licenses_desc' => '本頁提供 BookStack 使用到的專案以及函式庫的詳細授權資料,其中部份專案及函式庫僅開開發環境中使用。', 'licenses_bookstack' => 'BookStack 授權', - 'licenses_php' => 'PHP Library Licenses', - 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_php' => 'PHP 函式庫授權', + 'licenses_js' => 'JavaScript 函式庫授權', 'licenses_other' => '其它授權', - 'license_details' => 'License Details', + 'license_details' => '詳細授權資料', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. From f937bf3abb44db21fbada3180e66bfa27dc3f7da Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 21 May 2024 11:06:08 +0100 Subject: [PATCH 11/11] Updated translator & dependency attribution before release v24.05.1 --- .github/translators.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/translators.txt b/.github/translators.txt index cf77951b0..8667e5f0b 100644 --- a/.github/translators.txt +++ b/.github/translators.txt @@ -347,7 +347,7 @@ Taygun Yıldırım (yildirimtaygun) :: Turkish robing29 :: German Bruno Eduardo de Jesus Barroso (brunoejb) :: Portuguese, Brazilian Igor V Belousov (biv) :: Russian -David Bauer (davbauer) :: German +David Bauer (davbauer) :: German; German Informal Guttorm Hveem (guttormhveem) :: Norwegian Nynorsk; Norwegian Bokmal Minh Giang Truong (minhgiang1204) :: Vietnamese Ioannis Ioannides (i.ioannides) :: Greek @@ -389,7 +389,7 @@ Marc Hagen (MarcHagen) :: Dutch Kasper Alsøe (zeonos) :: Danish sultani :: Persian renge :: Korean -Tim (thegatesdev) :: Dutch; German Informal; Romanian; French; Catalan; Czech; Danish; German; Finnish; Hungarian; Italian; Japanese; Korean; Polish; Russian; Ukrainian; Chinese Simplified; Chinese Traditional; Portuguese, Brazilian; Persian; Spanish, Argentina; Croatian; Norwegian Nynorsk; Estonian; Uzbek; Norwegian Bokmal +Tim (thegatesdev) :: Dutch; German Informal; French; Romanian; Catalan; Czech; Danish; German; Finnish; Hungarian; Italian; Japanese; Korean; Polish; Russian; Ukrainian; Chinese Simplified; Chinese Traditional; Portuguese, Brazilian; Persian; Spanish, Argentina; Croatian; Norwegian Nynorsk; Estonian; Uzbek; Norwegian Bokmal Irdi (irdiOL) :: Albanian KateBarber :: Welsh Twister (theuncles75) :: Hebrew @@ -422,3 +422,6 @@ crow_ :: Latvian JocelynDelalande :: French Jan (JW-CH) :: German Informal Timo B (lommes) :: German Informal +Erik Lundstedt (Erik.Lundstedt) :: Swedish +yngams (younessmouhid) :: Arabic +Ohadp :: Hebrew