From 66a404ad1a83ca2f26c5f968935503306eb54578 Mon Sep 17 00:00:00 2001 From: Will Rossiter Date: Wed, 24 Oct 2018 12:11:57 +1300 Subject: [PATCH 01/17] FIX use Injector for FormField::castedCopy Allows LookupField to be replaced with user specificed classes. --- src/Forms/FormField.php | 2 +- src/Forms/TreeDropdownField_Readonly.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Forms/FormField.php b/src/Forms/FormField.php index 632335391..5a9b65bef 100644 --- a/src/Forms/FormField.php +++ b/src/Forms/FormField.php @@ -1424,7 +1424,7 @@ class FormField extends RequestHandler $field = $classOrCopy; if (!is_object($field)) { - $field = new $classOrCopy($this->name); + $field = $classOrCopy::create($this->name); } $field diff --git a/src/Forms/TreeDropdownField_Readonly.php b/src/Forms/TreeDropdownField_Readonly.php index fed1a1765..c51867098 100644 --- a/src/Forms/TreeDropdownField_Readonly.php +++ b/src/Forms/TreeDropdownField_Readonly.php @@ -17,7 +17,7 @@ class TreeDropdownField_Readonly extends TreeDropdownField } $source = [ $this->value => $title ]; - $field = new LookupField($this->name, $this->title, $source); + $field = LookupField::create($this->name, $this->title, $source); $field->setValue($this->value); $field->setForm($this->form); return $field->Field(); From 0610f76da02ac53a1b51cdfe9eac34e943a66991 Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Tue, 21 Aug 2018 11:20:15 +0100 Subject: [PATCH 02/17] [SS-2018-019] Add confirmation token to dev/build --- src/Control/HTTPApplication.php | 2 +- src/Core/Startup/ConfirmationToken.php | 182 ++++++++++++++++++ src/Core/Startup/ErrorControlChain.php | 3 +- .../Startup/ErrorControlChainMiddleware.php | 43 +++-- src/Core/Startup/ErrorDirector.php | 4 +- .../Startup/ParameterConfirmationToken.php | 172 +---------------- src/Core/Startup/URLConfirmationToken.php | 136 +++++++++++++ .../ErrorControlChainMiddlewareTest.php | 48 +++++ .../ParameterConfirmationTokenTest.php | 4 +- .../Core/Startup/URLConfirmationTokenTest.php | 148 ++++++++++++++ .../URLConfirmationTokenTest/StubToken.php | 27 +++ .../StubValidToken.php | 15 ++ 12 files changed, 600 insertions(+), 184 deletions(-) create mode 100644 src/Core/Startup/ConfirmationToken.php create mode 100644 src/Core/Startup/URLConfirmationToken.php create mode 100644 tests/php/Core/Startup/URLConfirmationTokenTest.php create mode 100644 tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php create mode 100644 tests/php/Core/Startup/URLConfirmationTokenTest/StubValidToken.php diff --git a/src/Control/HTTPApplication.php b/src/Control/HTTPApplication.php index 4d0f7cb9d..35f453d6d 100644 --- a/src/Control/HTTPApplication.php +++ b/src/Control/HTTPApplication.php @@ -41,7 +41,7 @@ class HTTPApplication implements Application */ public function handle(HTTPRequest $request) { - $flush = array_key_exists('flush', $request->getVars()) || strpos($request->getURL(), 'dev/build') === 0; + $flush = array_key_exists('flush', $request->getVars()) || ($request->getURL() === 'dev/build'); // Ensure boot is invoked return $this->execute($request, function (HTTPRequest $request) { diff --git a/src/Core/Startup/ConfirmationToken.php b/src/Core/Startup/ConfirmationToken.php new file mode 100644 index 000000000..d23563f46 --- /dev/null +++ b/src/Core/Startup/ConfirmationToken.php @@ -0,0 +1,182 @@ +reloadRequired() || $token->reloadRequiredIfError()) { + $token->suppress(); + $target = $token; + } + } + return $target; + } + + /** + * Generate a local filesystem path to store a token + * + * @param $token + * @return string + */ + protected function pathForToken($token) + { + return TEMP_PATH . DIRECTORY_SEPARATOR . 'token_' . preg_replace('/[^a-z0-9]+/', '', $token); + } + + /** + * Generate a new random token and store it + * + * @return string Token name + */ + protected function genToken() + { + // Generate a new random token (as random as possible) + $rg = new RandomGenerator(); + $token = $rg->randomToken('md5'); + + // Store a file in the session save path (safer than /tmp, as open_basedir might limit that) + file_put_contents($this->pathForToken($token), $token); + + return $token; + } + + /** + * Is the necessary token provided for this parameter? + * A value must be provided for the token + * + * @return bool + */ + public function tokenProvided() + { + return !empty($this->token); + } + + /** + * Validate a token + * + * @param string $token + * @return boolean True if the token is valid + */ + protected function checkToken($token) + { + if (!$token) { + return false; + } + + $file = $this->pathForToken($token); + $content = null; + + if (file_exists($file)) { + $content = file_get_contents($file); + unlink($file); + } + + return $content === $token; + } + + /** + * Get redirect url, excluding querystring + * + * @return string + */ + public function currentURL() + { + return Controller::join_links(Director::baseURL(), $this->request->getURL(false)); + } + + /** + * Forces a reload of the request with the token included + * + * @return HTTPResponse + */ + public function reloadWithToken() + { + $location = $this->redirectURL(); + $locationJS = Convert::raw2js($location); + $locationATT = Convert::raw2att($location); + $body = <<location.href='$locationJS'; + +You are being redirected. If you are not redirected soon, click here to continue +HTML; + + // Build response + $result = new HTTPResponse($body); + $result->redirect($location); + return $result; + } + + /** + * Is this parameter requested without a valid token? + * + * @return bool True if the parameter is given without a valid token + */ + abstract public function reloadRequired(); + + /** + * Check if this token is provided either in the backurl, or directly, + * but without a token + * + * @return bool + */ + abstract public function reloadRequiredIfError(); + + /** + * Suppress the current parameter for the duration of this request + */ + abstract public function suppress(); + + /** + * Determine the querystring parameters to include + * + * @param bool $includeToken Include the token value? + * @return array List of querystring parameters, possibly including token parameter + */ + abstract public function params($includeToken = true); + + /** + * Get redirection URL + * + * @return string + */ + abstract protected function redirectURL(); +} diff --git a/src/Core/Startup/ErrorControlChain.php b/src/Core/Startup/ErrorControlChain.php index f34a2c802..e2d14db65 100644 --- a/src/Core/Startup/ErrorControlChain.php +++ b/src/Core/Startup/ErrorControlChain.php @@ -15,8 +15,7 @@ use Exception; * $chain = new ErrorControlChain(); * $chain->then($callback1)->then($callback2)->thenIfErrored($callback3)->execute(); * - * WARNING: This class is experimental and designed specifically for use pre-startup. - * It will likely be heavily refactored before the release of 3.2 + * @internal This class is designed specifically for use pre-startup and may change without warning */ class ErrorControlChain { diff --git a/src/Core/Startup/ErrorControlChainMiddleware.php b/src/Core/Startup/ErrorControlChainMiddleware.php index bdb5ff0a3..e81444629 100644 --- a/src/Core/Startup/ErrorControlChainMiddleware.php +++ b/src/Core/Startup/ErrorControlChainMiddleware.php @@ -12,6 +12,8 @@ use SilverStripe\Security\Security; /** * Decorates application bootstrapping with errorcontrolchain + * + * @internal This class is designed specifically for use pre-startup and may change without warning */ class ErrorControlChainMiddleware implements HTTPMiddleware { @@ -30,27 +32,42 @@ class ErrorControlChainMiddleware implements HTTPMiddleware $this->application = $application; } + /** + * @param HTTPRequest $request + * @return ConfirmationToken|null + */ + protected function prepareConfirmationTokenIfRequired(HTTPRequest $request) + { + $token = URLConfirmationToken::prepare_tokens(['dev/build'], $request); + + if (!$token) { + $token = ParameterConfirmationToken::prepare_tokens( + ['isTest', 'isDev', 'flush'], + $request + ); + } + + return $token; + } + public function process(HTTPRequest $request, callable $next) { $result = null; // Prepare tokens and execute chain - $reloadToken = ParameterConfirmationToken::prepare_tokens( - ['isTest', 'isDev', 'flush'], - $request - ); + $confirmationToken = $this->prepareConfirmationTokenIfRequired($request); $chain = new ErrorControlChain(); $chain - ->then(function () use ($request, $chain, $reloadToken, $next, &$result) { + ->then(function () use ($request, $chain, $confirmationToken, $next, &$result) { // If no redirection is necessary then we can disable error supression - if (!$reloadToken) { + if (!$confirmationToken) { $chain->setSuppression(false); } try { // Check if a token is requesting a redirect - if ($reloadToken && $reloadToken->reloadRequired()) { - $result = $this->safeReloadWithToken($request, $reloadToken); + if ($confirmationToken && $confirmationToken->reloadRequired()) { + $result = $this->safeReloadWithToken($request, $confirmationToken); } else { // If no reload necessary, process application $result = call_user_func($next, $request); @@ -60,9 +77,9 @@ class ErrorControlChainMiddleware implements HTTPMiddleware } }) // Finally if a token was requested but there was an error while figuring out if it's allowed, do it anyway - ->thenIfErrored(function () use ($reloadToken) { - if ($reloadToken && $reloadToken->reloadRequiredIfError()) { - $result = $reloadToken->reloadWithToken(); + ->thenIfErrored(function () use ($confirmationToken) { + if ($confirmationToken && $confirmationToken->reloadRequiredIfError()) { + $result = $confirmationToken->reloadWithToken(); $result->output(); } }) @@ -85,7 +102,7 @@ class ErrorControlChainMiddleware implements HTTPMiddleware // Ensure session is started $request->getSession()->init($request); - + // Request with ErrorDirector $result = ErrorDirector::singleton()->handleRequestWithToken( $request, @@ -98,7 +115,7 @@ class ErrorControlChainMiddleware implements HTTPMiddleware // Fail and redirect the user to the login page $params = array_merge($request->getVars(), $reloadToken->params(false)); - $backURL = $request->getURL() . '?' . http_build_query($params); + $backURL = $reloadToken->currentURL() . '?' . http_build_query($params); $loginPage = Director::absoluteURL(Security::config()->get('login_url')); $loginPage .= "?BackURL=" . urlencode($backURL); $result = new HTTPResponse(); diff --git a/src/Core/Startup/ErrorDirector.php b/src/Core/Startup/ErrorDirector.php index 3c994c6af..54001fd05 100644 --- a/src/Core/Startup/ErrorDirector.php +++ b/src/Core/Startup/ErrorDirector.php @@ -21,11 +21,11 @@ class ErrorDirector extends Director * Redirect with token if allowed, or null if not allowed * * @param HTTPRequest $request - * @param ParameterConfirmationToken $token + * @param ConfirmationToken $token * @param Kernel $kernel * @return null|HTTPResponse Redirection response, or null if not able to redirect */ - public function handleRequestWithToken(HTTPRequest $request, ParameterConfirmationToken $token, Kernel $kernel) + public function handleRequestWithToken(HTTPRequest $request, ConfirmationToken $token, Kernel $kernel) { Injector::inst()->registerService($request, HTTPRequest::class); diff --git a/src/Core/Startup/ParameterConfirmationToken.php b/src/Core/Startup/ParameterConfirmationToken.php index 1c80db1d0..4e90f1ef7 100644 --- a/src/Core/Startup/ParameterConfirmationToken.php +++ b/src/Core/Startup/ParameterConfirmationToken.php @@ -9,30 +9,21 @@ use SilverStripe\Core\Convert; use SilverStripe\Security\RandomGenerator; /** - * Class ParameterConfirmationToken + * This is used to protect dangerous GET parameters that need to be detected early in the request + * lifecycle by generating a one-time-use token & redirecting with that token included in the + * redirected URL * - * When you need to use a dangerous GET parameter that needs to be set before core/Core.php is - * established, this class takes care of allowing some other code of confirming the parameter, - * by generating a one-time-use token & redirecting with that token included in the redirected URL - * - * WARNING: This class is experimental and designed specifically for use pre-startup. - * It will likely be heavily refactored before the release of 3.2 + * @internal This class is designed specifically for use pre-startup and may change without warning */ -class ParameterConfirmationToken +class ParameterConfirmationToken extends ConfirmationToken { - /** * The name of the parameter * * @var string */ protected $parameterName = null; - - /** - * @var HTTPRequest - */ - protected $request = null; - + /** * The parameter given in the main request * @@ -48,60 +39,6 @@ class ParameterConfirmationToken protected $parameterBackURL = null; /** - * The validated and checked token for this parameter - * - * @var string|null A string value, or null if either not provided or invalid - */ - protected $token = null; - - protected function pathForToken($token) - { - return TEMP_PATH . DIRECTORY_SEPARATOR . 'token_' . preg_replace('/[^a-z0-9]+/', '', $token); - } - - /** - * Generate a new random token and store it - * - * @return string Token name - */ - protected function genToken() - { - // Generate a new random token (as random as possible) - $rg = new RandomGenerator(); - $token = $rg->randomToken('md5'); - - // Store a file in the session save path (safer than /tmp, as open_basedir might limit that) - file_put_contents($this->pathForToken($token), $token); - - return $token; - } - - /** - * Validate a token - * - * @param string $token - * @return boolean True if the token is valid - */ - protected function checkToken($token) - { - if (!$token) { - return false; - } - - $file = $this->pathForToken($token); - $content = null; - - if (file_exists($file)) { - $content = file_get_contents($file); - unlink($file); - } - - return $content == $token; - } - - /** - * Create a new ParameterConfirmationToken - * * @param string $parameterName Name of the querystring parameter to check * @param HTTPRequest $request */ @@ -176,54 +113,23 @@ class ParameterConfirmationToken return $this->parameterBackURL !== null; } - /** - * Is the necessary token provided for this parameter? - * A value must be provided for the token - * - * @return bool - */ - public function tokenProvided() - { - return !empty($this->token); - } - - /** - * Is this parameter requested without a valid token? - * - * @return bool True if the parameter is given without a valid token - */ public function reloadRequired() { return $this->parameterProvided() && !$this->tokenProvided(); } - /** - * Check if this token is provided either in the backurl, or directly, - * but without a token - * - * @return bool - */ public function reloadRequiredIfError() { // Don't reload if token exists return $this->reloadRequired() || $this->existsInReferer(); } - - /** - * Suppress the current parameter by unsetting it from $_GET - */ + public function suppress() { unset($_GET[$this->parameterName]); $this->request->offsetUnset($this->parameterName); } - /** - * Determine the querystring parameters to include - * - * @param bool $includeToken Include the token value as well? - * @return array List of querystring parameters with name and token parameters - */ public function params($includeToken = true) { $params = array( @@ -234,25 +140,7 @@ class ParameterConfirmationToken } return $params; } - - /** - * Get redirect url, excluding querystring - * - * @return string - */ - protected function currentURL() - { - return Controller::join_links( - BASE_URL ?: '/', - $this->request->getURL(false) - ); - } - - /** - * Get redirection URL - * - * @return string - */ + protected function redirectURL() { // If url is encoded via BackURL, defer to home page (prevent redirect to form action) @@ -267,48 +155,4 @@ class ParameterConfirmationToken // Merge get params with current url return Controller::join_links($url, '?' . http_build_query($params)); } - - /** - * Forces a reload of the request with the token included - * - * @return HTTPResponse - */ - public function reloadWithToken() - { - $location = $this->redirectURL(); - $locationJS = Convert::raw2js($location); - $locationATT = Convert::raw2att($location); - $body = <<location.href='$locationJS'; - -You are being redirected. If you are not redirected soon, click here to continue the flush -HTML; - - // Build response - $result = new HTTPResponse($body); - $result->redirect($location); - return $result; - } - - /** - * Given a list of token names, suppress all tokens that have not been validated, and - * return the non-validated token with the highest priority - * - * @param array $keys List of token keys in ascending priority (low to high) - * @param HTTPRequest $request - * @return ParameterConfirmationToken The token container for the unvalidated $key given with the highest priority - */ - public static function prepare_tokens($keys, HTTPRequest $request) - { - $target = null; - foreach ($keys as $key) { - $token = new ParameterConfirmationToken($key, $request); - // Validate this token - if ($token->reloadRequired() || $token->reloadRequiredIfError()) { - $token->suppress(); - $target = $token; - } - } - return $target; - } } diff --git a/src/Core/Startup/URLConfirmationToken.php b/src/Core/Startup/URLConfirmationToken.php new file mode 100644 index 000000000..8176a41b8 --- /dev/null +++ b/src/Core/Startup/URLConfirmationToken.php @@ -0,0 +1,136 @@ +urlToCheck = $urlToCheck; + $this->request = $request; + $this->currentURL = $request->getURL(false); + + $this->tokenParameterName = preg_replace('/[^a-z0-9]/i', '', $urlToCheck) . 'token'; + $this->urlExistsInBackURL = $this->getURLExistsInBackURL($request); + + // If the token provided is valid, mark it as such + $token = $request->getVar($this->tokenParameterName); + if ($this->checkToken($token)) { + $this->token = $token; + } + } + + /** + * @param HTTPRequest $request + * @return bool + */ + protected function getURLExistsInBackURL(HTTPRequest $request) + { + $backURL = $request->getVar('BackURL'); + return (strpos($backURL, $this->urlToCheck) === 0); + } + + /** + * @return bool + */ + protected function urlMatches() + { + return ($this->currentURL === $this->urlToCheck); + } + + /** + * @return string + */ + public function getURLToCheck() + { + return $this->urlToCheck; + } + + /** + * @return bool + */ + public function urlExistsInBackURL() + { + return $this->urlExistsInBackURL; + } + + public function reloadRequired() + { + return $this->urlMatches() && !$this->tokenProvided(); + } + + public function reloadRequiredIfError() + { + return $this->reloadRequired() || $this->urlExistsInBackURL(); + } + + public function suppress() + { + $_SERVER['REQUEST_URI'] = '/'; + $this->request->setURL('/'); + } + + public function params($includeToken = true) + { + $params = []; + if ($includeToken) { + $params[$this->tokenParameterName] = $this->genToken(); + } + + return $params; + } + + public function currentURL() + { + return Controller::join_links(Director::baseURL(), $this->currentURL); + } + + protected function redirectURL() + { + // If url is encoded via BackURL, defer to home page (prevent redirect to form action) + if ($this->urlExistsInBackURL && !$this->urlMatches()) { + $url = BASE_URL ?: '/'; + $params = $this->params(); + } else { + $url = $this->currentURL(); + $params = array_merge($this->request->getVars(), $this->params()); + } + + // Merge get params with current url + return Controller::join_links($url, '?' . http_build_query($params)); + } +} diff --git a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php index 5cce89d3e..7df6f6ebf 100644 --- a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php +++ b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php @@ -73,4 +73,52 @@ class ErrorControlChainMiddlewareTest extends SapphireTest $this->assertNotContains('?flush=1&flushtoken=', $location); $this->assertContains('Security/login', $location); } + + public function testLiveBuildAdmin() + { + // Mock admin + $adminID = $this->logInWithPermission('ADMIN'); + $this->logOut(); + + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as admin + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build/'); + $request->setSession(new Session(['loggedInAs' => $adminID])); + $result = $chain->process($request, function () { + return null; + }); + + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertContains('/dev/build', $location); + $this->assertContains('?devbuildtoken=', $location); + $this->assertNotContains('Security/login', $location); + } + + public function testLiveBuildUnauthenticated() + { + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as no one + Security::setCurrentUser(null); + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build'); + $request->setSession(new Session(['loggedInAs' => 0])); + $result = $chain->process($request, function () { + return null; + }); + + // Should be directed to login, not to flush + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertNotContains('/dev/build', $location); + $this->assertNotContains('?devbuildtoken=', $location); + $this->assertContains('Security/login', $location); + } } diff --git a/tests/php/Core/Startup/ParameterConfirmationTokenTest.php b/tests/php/Core/Startup/ParameterConfirmationTokenTest.php index 66616433f..e28af8ea5 100644 --- a/tests/php/Core/Startup/ParameterConfirmationTokenTest.php +++ b/tests/php/Core/Startup/ParameterConfirmationTokenTest.php @@ -149,14 +149,14 @@ class ParameterConfirmationTokenTest extends SapphireTest } /** - * currentAbsoluteURL needs to handle base or url being missing, or any combination of slashes. + * currentURL needs to handle base or url being missing, or any combination of slashes. * * There should always be exactly one slash between each part in the result, and any trailing slash * should be preserved. * * @dataProvider dataProviderURLs */ - public function testCurrentAbsoluteURLHandlesSlashes($url) + public function testCurrentURLHandlesSlashes($url) { $this->request->setUrl($url); diff --git a/tests/php/Core/Startup/URLConfirmationTokenTest.php b/tests/php/Core/Startup/URLConfirmationTokenTest.php new file mode 100644 index 000000000..73b07eb13 --- /dev/null +++ b/tests/php/Core/Startup/URLConfirmationTokenTest.php @@ -0,0 +1,148 @@ + 'value']); + $validToken = new StubValidToken('token/test/url', $request); + $this->assertTrue($validToken->urlMatches()); + $this->assertFalse($validToken->urlExistsInBackURL()); + $this->assertTrue($validToken->tokenProvided()); // Actually forced to true for this test + $this->assertFalse($validToken->reloadRequired()); + $this->assertFalse($validToken->reloadRequiredIfError()); + $this->assertStringStartsWith(Controller::join_links(BASE_URL, '/', 'token/test/url'), $validToken->redirectURL()); + } + + public function testTokenWithLeadingSlashInUrl() + { + $request = new HTTPRequest('GET', '/leading/slash/url', []); + $leadingSlash = new StubToken('leading/slash/url', $request); + $this->assertTrue($leadingSlash->urlMatches()); + $this->assertFalse($leadingSlash->urlExistsInBackURL()); + $this->assertFalse($leadingSlash->tokenProvided()); + $this->assertTrue($leadingSlash->reloadRequired()); + $this->assertTrue($leadingSlash->reloadRequiredIfError()); + $this->assertContains('leading/slash/url', $leadingSlash->redirectURL()); + $this->assertContains('leadingslashurltoken', $leadingSlash->redirectURL()); + } + + public function testTokenWithTrailingSlashInUrl() + { + $request = new HTTPRequest('GET', 'trailing/slash/url/', []); + $trailingSlash = new StubToken('trailing/slash/url', $request); + $this->assertTrue($trailingSlash->urlMatches()); + $this->assertFalse($trailingSlash->urlExistsInBackURL()); + $this->assertFalse($trailingSlash->tokenProvided()); + $this->assertTrue($trailingSlash->reloadRequired()); + $this->assertTrue($trailingSlash->reloadRequiredIfError()); + $this->assertContains('trailing/slash/url', $trailingSlash->redirectURL()); + $this->assertContains('trailingslashurltoken', $trailingSlash->redirectURL()); + } + + public function testTokenWithUrlMatchedInBackUrl() + { + $request = new HTTPRequest('GET', '/', ['BackURL' => 'back/url']); + $backUrl = new StubToken('back/url', $request); + $this->assertFalse($backUrl->urlMatches()); + $this->assertTrue($backUrl->urlExistsInBackURL()); + $this->assertFalse($backUrl->tokenProvided()); + $this->assertFalse($backUrl->reloadRequired()); + $this->assertTrue($backUrl->reloadRequiredIfError()); + $home = (BASE_URL ?: '/') . '?'; + $this->assertStringStartsWith($home, $backUrl->redirectURL()); + $this->assertContains('backurltoken', $backUrl->redirectURL()); + } + + public function testUrlSuppressionWhenTokenMissing() + { + // Check suppression + $request = new HTTPRequest('GET', 'test/url', []); + $token = new StubToken('test/url', $request); + $this->assertEquals('test/url', $request->getURL(false)); + $token->suppress(); + $this->assertEquals('', $request->getURL(false)); + } + + public function testPrepareTokens() + { + $request = new HTTPRequest('GET', 'test/url', []); + $token = URLConfirmationToken::prepare_tokens( + [ + 'test/url', + 'test', + 'url' + ], + $request + ); + // Test no invalid tokens + $this->assertEquals('test/url', $token->getURLToCheck()); + $this->assertNotEquals('test/url', $request->getURL(false), 'prepare_tokens() did not suppress URL'); + } + + public function testPrepareTokensDoesntSuppressWhenNotMatched() + { + $request = new HTTPRequest('GET', 'test/url', []); + $token = URLConfirmationToken::prepare_tokens( + ['another/url'], + $request + ); + $this->assertEmpty($token); + $this->assertEquals('test/url', $request->getURL(false), 'prepare_tokens() incorrectly suppressed URL'); + } + + public function testPrepareTokensWithUrlMatchedInBackUrl() + { + // Test backurl token + $request = new HTTPRequest('GET', '/', ['BackURL' => 'back/url']); + $token = URLConfirmationToken::prepare_tokens( + [ 'back/url' ], + $request + ); + $this->assertNotEmpty($token); + $this->assertEquals('back/url', $token->getURLToCheck()); + $this->assertNotEquals('back/url', $request->getURL(false), 'prepare_tokens() did not suppress URL'); + } + + public function dataProviderURLs() + { + return [ + [''], + ['/'], + ['bar'], + ['bar/'], + ['/bar'], + ['/bar/'], + ]; + } + + /** + * currentURL needs to handle base or url being missing, or any combination of slashes. + * + * There should always be exactly one slash between each part in the result, and any trailing slash + * should be preserved. + * + * @dataProvider dataProviderURLs + */ + public function testCurrentURLHandlesSlashes($url) + { + $request = new HTTPRequest('GET', $url, []); + + $token = new StubToken( + 'another/url', + $request + ); + $expected = rtrim(Controller::join_links(BASE_URL, '/', $url), '/') ?: '/'; + $this->assertEquals($expected, $token->currentURL(), "Invalid redirect for request url $url"); + } +} diff --git a/tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php b/tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php new file mode 100644 index 000000000..ca08d3e1f --- /dev/null +++ b/tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php @@ -0,0 +1,27 @@ + Date: Mon, 30 Jul 2018 11:50:11 +1200 Subject: [PATCH 03/17] [SS-2018-018] Ignore arguments in mysqli::real_connect backtrace calls --- src/Dev/Backtrace.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Dev/Backtrace.php b/src/Dev/Backtrace.php index daceca751..648cc883f 100644 --- a/src/Dev/Backtrace.php +++ b/src/Dev/Backtrace.php @@ -26,6 +26,7 @@ class Backtrace array('PDO', '__construct'), array('mysqli', 'mysqli'), array('mysqli', 'select_db'), + array('mysqli', 'real_connect'), array('SilverStripe\\ORM\\DB', 'connect'), array('SilverStripe\\Security\\Security', 'check_default_admin'), array('SilverStripe\\Security\\Security', 'encrypt_password'), From 5563537cc8c2383ba5fbe039886b10c4444f6434 Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Fri, 24 Aug 2018 15:36:51 +0100 Subject: [PATCH 04/17] Implement ConfirmationTokenChain to handle multiple tokens at once --- ...oken.php => AbstractConfirmationToken.php} | 12 +- src/Core/Startup/ConfirmationTokenChain.php | 178 +++++++++++++++++ .../Startup/ErrorControlChainMiddleware.php | 62 +++--- src/Core/Startup/ErrorDirector.php | 13 +- .../Startup/ParameterConfirmationToken.php | 28 +-- src/Core/Startup/URLConfirmationToken.php | 29 +-- .../Startup/ConfirmationTokenChainTest.php | 185 ++++++++++++++++++ .../ErrorControlChainMiddlewareTest.php | 52 +++++ 8 files changed, 500 insertions(+), 59 deletions(-) rename src/Core/Startup/{ConfirmationToken.php => AbstractConfirmationToken.php} (95%) create mode 100644 src/Core/Startup/ConfirmationTokenChain.php create mode 100644 tests/php/Core/Startup/ConfirmationTokenChainTest.php diff --git a/src/Core/Startup/ConfirmationToken.php b/src/Core/Startup/AbstractConfirmationToken.php similarity index 95% rename from src/Core/Startup/ConfirmationToken.php rename to src/Core/Startup/AbstractConfirmationToken.php index d23563f46..11f78b48a 100644 --- a/src/Core/Startup/ConfirmationToken.php +++ b/src/Core/Startup/AbstractConfirmationToken.php @@ -15,7 +15,7 @@ use SilverStripe\Security\RandomGenerator; * * @internal This class is designed specifically for use pre-startup and may change without warning */ -abstract class ConfirmationToken +abstract class AbstractConfirmationToken { /** * @var HTTPRequest @@ -173,6 +173,16 @@ HTML; */ abstract public function params($includeToken = true); + /** + * @return string + */ + abstract public function getRedirectUrlBase(); + + /** + * @return array + */ + abstract public function getRedirectUrlParams(); + /** * Get redirection URL * diff --git a/src/Core/Startup/ConfirmationTokenChain.php b/src/Core/Startup/ConfirmationTokenChain.php new file mode 100644 index 000000000..a47f2c4c0 --- /dev/null +++ b/src/Core/Startup/ConfirmationTokenChain.php @@ -0,0 +1,178 @@ +tokens[] = $token; + } + + /** + * Collect all tokens that require a redirect + * + * @return \Generator + */ + protected function filteredTokens() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequired() || $token->reloadRequiredIfError()) { + yield $token; + } + } + } + + /** + * @return bool + */ + public function suppressionRequired() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequired()) { + return true; + } + } + + return false; + } + + /** + * Suppress URLs & GET vars from tokens that require a redirect + */ + public function suppressTokens() + { + foreach ($this->filteredTokens() as $token) { + $token->suppress(); + } + } + + /** + * @return bool + */ + public function reloadRequired() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequired()) { + return true; + } + } + + return false; + } + + /** + * @return bool + */ + public function reloadRequiredIfError() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequiredIfError()) { + return true; + } + } + + return false; + } + + /** + * @param bool $includeToken + * @return array + */ + public function params($includeToken = true) + { + $params = []; + foreach ($this->tokens as $token) { + $params = array_merge($params, $token->params($includeToken)); + } + + return $params; + } + + /** + * Fetch the URL we want to redirect to, excluding query string parameters. This may + * be the same URL (with a token to be added outside this method), or to a different + * URL if the current one has been suppressed + * + * @return string + */ + public function getRedirectUrlBase() + { + // URLConfirmationTokens may alter the URL to suppress the URL they're protecting, + // so we need to ensure they're inspected last and therefore take priority + $tokens = iterator_to_array($this->filteredTokens(), false); + usort($tokens, function ($a, $b) { + return ($a instanceof URLConfirmationToken) ? 1 : 0; + }); + + $urlBase = Director::baseURL(); + foreach ($tokens as $token) { + $urlBase = $token->getRedirectUrlBase(); + } + + return $urlBase; + } + + /** + * Collate GET vars from all token providers that need to apply a token + * + * @return array + */ + public function getRedirectUrlParams() + { + $params = []; + foreach ($this->filteredTokens() as $token) { + $params = array_merge($params, $token->getRedirectUrlParams()); + } + + return $params; + } + + /** + * @return string + */ + protected function redirectURL() + { + $params = http_build_query($this->getRedirectUrlParams()); + return Controller::join_links($this->getRedirectUrlBase(), '?' . $params); + } + + /** + * @return HTTPResponse + */ + public function reloadWithTokens() + { + $location = $this->redirectURL(); + $locationJS = Convert::raw2js($location); + $locationATT = Convert::raw2att($location); + $body = <<location.href='$locationJS'; + +You are being redirected. If you are not redirected soon, click here to continue +HTML; + + // Build response + $result = new HTTPResponse($body); + $result->redirect($location); + return $result; + } +} diff --git a/src/Core/Startup/ErrorControlChainMiddleware.php b/src/Core/Startup/ErrorControlChainMiddleware.php index e81444629..c29878e15 100644 --- a/src/Core/Startup/ErrorControlChainMiddleware.php +++ b/src/Core/Startup/ErrorControlChainMiddleware.php @@ -34,20 +34,18 @@ class ErrorControlChainMiddleware implements HTTPMiddleware /** * @param HTTPRequest $request - * @return ConfirmationToken|null + * @return ConfirmationTokenChain */ - protected function prepareConfirmationTokenIfRequired(HTTPRequest $request) + protected function prepareConfirmationTokenChain(HTTPRequest $request) { - $token = URLConfirmationToken::prepare_tokens(['dev/build'], $request); + $chain = new ConfirmationTokenChain(); + $chain->pushToken(new URLConfirmationToken('dev/build', $request)); - if (!$token) { - $token = ParameterConfirmationToken::prepare_tokens( - ['isTest', 'isDev', 'flush'], - $request - ); + foreach (['isTest', 'isDev', 'flush'] as $parameter) { + $chain->pushToken(new ParameterConfirmationToken($parameter, $request)); } - return $token; + return $chain; } public function process(HTTPRequest $request, callable $next) @@ -55,19 +53,21 @@ class ErrorControlChainMiddleware implements HTTPMiddleware $result = null; // Prepare tokens and execute chain - $confirmationToken = $this->prepareConfirmationTokenIfRequired($request); - $chain = new ErrorControlChain(); - $chain - ->then(function () use ($request, $chain, $confirmationToken, $next, &$result) { - // If no redirection is necessary then we can disable error supression - if (!$confirmationToken) { - $chain->setSuppression(false); + $confirmationTokenChain = $this->prepareConfirmationTokenChain($request); + $errorControlChain = new ErrorControlChain(); + $errorControlChain + ->then(function () use ($request, $errorControlChain, $confirmationTokenChain, $next, &$result) { + if ($confirmationTokenChain->suppressionRequired()) { + $confirmationTokenChain->suppressTokens(); + } else { + // If no redirection is necessary then we can disable error supression + $errorControlChain->setSuppression(false); } try { // Check if a token is requesting a redirect - if ($confirmationToken && $confirmationToken->reloadRequired()) { - $result = $this->safeReloadWithToken($request, $confirmationToken); + if ($confirmationTokenChain && $confirmationTokenChain->reloadRequired()) { + $result = $this->safeReloadWithTokens($request, $confirmationTokenChain); } else { // If no reload necessary, process application $result = call_user_func($next, $request); @@ -77,10 +77,16 @@ class ErrorControlChainMiddleware implements HTTPMiddleware } }) // Finally if a token was requested but there was an error while figuring out if it's allowed, do it anyway - ->thenIfErrored(function () use ($confirmationToken) { - if ($confirmationToken && $confirmationToken->reloadRequiredIfError()) { - $result = $confirmationToken->reloadWithToken(); - $result->output(); + ->thenIfErrored(function () use ($confirmationTokenChain) { + if ($confirmationTokenChain && $confirmationTokenChain->reloadRequiredIfError()) { + try { + // Reload requires manual boot + $this->getApplication()->getKernel()->boot(false); + } finally { + // Given we're in an error state here, try to continue even if the kernel boot fails + $result = $confirmationTokenChain->reloadWithTokens(); + $result->output(); + } } }) ->execute(); @@ -92,10 +98,10 @@ class ErrorControlChainMiddleware implements HTTPMiddleware * or authentication is impossible. * * @param HTTPRequest $request - * @param ParameterConfirmationToken $reloadToken + * @param ConfirmationTokenChain $confirmationTokenChain * @return HTTPResponse */ - protected function safeReloadWithToken(HTTPRequest $request, $reloadToken) + protected function safeReloadWithTokens(HTTPRequest $request, ConfirmationTokenChain $confirmationTokenChain) { // Safe reload requires manual boot $this->getApplication()->getKernel()->boot(false); @@ -104,9 +110,9 @@ class ErrorControlChainMiddleware implements HTTPMiddleware $request->getSession()->init($request); // Request with ErrorDirector - $result = ErrorDirector::singleton()->handleRequestWithToken( + $result = ErrorDirector::singleton()->handleRequestWithTokenChain( $request, - $reloadToken, + $confirmationTokenChain, $this->getApplication()->getKernel() ); if ($result) { @@ -114,8 +120,8 @@ class ErrorControlChainMiddleware implements HTTPMiddleware } // Fail and redirect the user to the login page - $params = array_merge($request->getVars(), $reloadToken->params(false)); - $backURL = $reloadToken->currentURL() . '?' . http_build_query($params); + $params = array_merge($request->getVars(), $confirmationTokenChain->params(false)); + $backURL = $confirmationTokenChain->getRedirectUrlBase() . '?' . http_build_query($params); $loginPage = Director::absoluteURL(Security::config()->get('login_url')); $loginPage .= "?BackURL=" . urlencode($backURL); $result = new HTTPResponse(); diff --git a/src/Core/Startup/ErrorDirector.php b/src/Core/Startup/ErrorDirector.php index 54001fd05..575df7183 100644 --- a/src/Core/Startup/ErrorDirector.php +++ b/src/Core/Startup/ErrorDirector.php @@ -21,18 +21,21 @@ class ErrorDirector extends Director * Redirect with token if allowed, or null if not allowed * * @param HTTPRequest $request - * @param ConfirmationToken $token + * @param ConfirmationTokenChain $confirmationTokenChain * @param Kernel $kernel * @return null|HTTPResponse Redirection response, or null if not able to redirect */ - public function handleRequestWithToken(HTTPRequest $request, ConfirmationToken $token, Kernel $kernel) - { + public function handleRequestWithTokenChain( + HTTPRequest $request, + ConfirmationTokenChain $confirmationTokenChain, + Kernel $kernel + ) { Injector::inst()->registerService($request, HTTPRequest::class); // Next, check if we're in dev mode, or the database doesn't have any security data, or we are admin - $reload = function (HTTPRequest $request) use ($token, $kernel) { + $reload = function (HTTPRequest $request) use ($confirmationTokenChain, $kernel) { if ($kernel->getEnvironment() === Kernel::DEV || !Security::database_is_ready() || Permission::check('ADMIN')) { - return $token->reloadWithToken(); + return $confirmationTokenChain->reloadWithTokens(); } return null; }; diff --git a/src/Core/Startup/ParameterConfirmationToken.php b/src/Core/Startup/ParameterConfirmationToken.php index 4e90f1ef7..bc751a2c3 100644 --- a/src/Core/Startup/ParameterConfirmationToken.php +++ b/src/Core/Startup/ParameterConfirmationToken.php @@ -3,6 +3,7 @@ namespace SilverStripe\Core\Startup; use SilverStripe\Control\Controller; +use SilverStripe\Control\Director; use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; use SilverStripe\Core\Convert; @@ -15,7 +16,7 @@ use SilverStripe\Security\RandomGenerator; * * @internal This class is designed specifically for use pre-startup and may change without warning */ -class ParameterConfirmationToken extends ConfirmationToken +class ParameterConfirmationToken extends AbstractConfirmationToken { /** * The name of the parameter @@ -140,19 +141,22 @@ class ParameterConfirmationToken extends ConfirmationToken } return $params; } + + public function getRedirectUrlBase() + { + return ($this->existsInReferer() && !$this->parameterProvided()) ? Director::baseURL() : $this->currentURL(); + } + + public function getRedirectUrlParams() + { + return ($this->existsInReferer() && !$this->parameterProvided()) + ? $this->params() + : array_merge($this->request->getVars(), $this->params()); + } protected function redirectURL() { - // If url is encoded via BackURL, defer to home page (prevent redirect to form action) - if ($this->existsInReferer() && !$this->parameterProvided()) { - $url = BASE_URL ?: '/'; - $params = $this->params(); - } else { - $url = $this->currentURL(); - $params = array_merge($this->request->getVars(), $this->params()); - } - - // Merge get params with current url - return Controller::join_links($url, '?' . http_build_query($params)); + $query = http_build_query($this->getRedirectUrlParams()); + return Controller::join_links($this->getRedirectUrlBase(), '?' . $query); } } diff --git a/src/Core/Startup/URLConfirmationToken.php b/src/Core/Startup/URLConfirmationToken.php index 8176a41b8..bb509931e 100644 --- a/src/Core/Startup/URLConfirmationToken.php +++ b/src/Core/Startup/URLConfirmationToken.php @@ -12,7 +12,7 @@ use SilverStripe\Control\HTTPRequest; * * @internal This class is designed specifically for use pre-startup and may change without warning */ -class URLConfirmationToken extends ConfirmationToken +class URLConfirmationToken extends AbstractConfirmationToken { /** * @var string @@ -60,7 +60,7 @@ class URLConfirmationToken extends ConfirmationToken */ protected function getURLExistsInBackURL(HTTPRequest $request) { - $backURL = $request->getVar('BackURL'); + $backURL = ltrim($request->getVar('BackURL'), '/'); return (strpos($backURL, $this->urlToCheck) === 0); } @@ -119,18 +119,21 @@ class URLConfirmationToken extends ConfirmationToken return Controller::join_links(Director::baseURL(), $this->currentURL); } + public function getRedirectUrlBase() + { + return ($this->urlExistsInBackURL && !$this->urlMatches()) ? Director::baseURL() : $this->currentURL(); + } + + public function getRedirectUrlParams() + { + return ($this->urlExistsInBackURL && !$this->urlMatches()) + ? $this->params() + : array_merge($this->request->getVars(), $this->params()); + } + protected function redirectURL() { - // If url is encoded via BackURL, defer to home page (prevent redirect to form action) - if ($this->urlExistsInBackURL && !$this->urlMatches()) { - $url = BASE_URL ?: '/'; - $params = $this->params(); - } else { - $url = $this->currentURL(); - $params = array_merge($this->request->getVars(), $this->params()); - } - - // Merge get params with current url - return Controller::join_links($url, '?' . http_build_query($params)); + $query = http_build_query($this->getRedirectUrlParams()); + return Controller::join_links($this->getRedirectUrlBase(), '?' . $query); } } diff --git a/tests/php/Core/Startup/ConfirmationTokenChainTest.php b/tests/php/Core/Startup/ConfirmationTokenChainTest.php new file mode 100644 index 000000000..adb8fba36 --- /dev/null +++ b/tests/php/Core/Startup/ConfirmationTokenChainTest.php @@ -0,0 +1,185 @@ +createPartialMock(ParameterConfirmationToken::class, $methods); + $mock->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue($requiresReload)); + return $mock; + } + + protected function getTokenRequiringReloadIfError($requiresReload = true, $extraMethods = []) + { + $methods = array_merge(['reloadRequired', 'reloadRequiredIfError'], $extraMethods); + $mock = $this->createPartialMock(ParameterConfirmationToken::class, $methods); + $mock->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue(false)); + $mock->expects($this->any()) + ->method('reloadRequiredIfError') + ->will($this->returnValue($requiresReload)); + return $mock; + } + + public function testFilteredTokens() + { + $chain = new ConfirmationTokenChain(); + $chain->pushToken($tokenRequiringReload = $this->getTokenRequiringReload()); + $chain->pushToken($tokenNotRequiringReload = $this->getTokenRequiringReload(false)); + $chain->pushToken($tokenRequiringReloadIfError = $this->getTokenRequiringReloadIfError()); + $chain->pushToken($tokenNotRequiringReloadIfError = $this->getTokenRequiringReloadIfError(false)); + + $reflectionMethod = new \ReflectionMethod(ConfirmationTokenChain::class, 'filteredTokens'); + $reflectionMethod->setAccessible(true); + $tokens = iterator_to_array($reflectionMethod->invoke($chain)); + + $this->assertContains($tokenRequiringReload, $tokens, 'Token requiring a reload was not returned'); + $this->assertNotContains($tokenNotRequiringReload, $tokens, 'Token not requiring a reload was returned'); + $this->assertContains($tokenRequiringReloadIfError, $tokens, 'Token requiring a reload on error was not returned'); + $this->assertNotContains($tokenNotRequiringReloadIfError, $tokens, 'Token not requiring a reload on error was returned'); + } + + public function testSuppressionRequired() + { + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReload(false)); + $this->assertFalse($chain->suppressionRequired(), 'Suppression incorrectly marked as required'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReloadIfError(false)); + $this->assertFalse($chain->suppressionRequired(), 'Suppression incorrectly marked as required'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReload()); + $this->assertTrue($chain->suppressionRequired(), 'Suppression not marked as required'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReloadIfError()); + $this->assertFalse($chain->suppressionRequired(), 'Suppression incorrectly marked as required'); + } + + public function testSuppressTokens() + { + $mockToken = $this->getTokenRequiringReload(true, ['suppress']); + $mockToken->expects($this->once()) + ->method('suppress'); + $secondMockToken = $this->getTokenRequiringReloadIfError(true, ['suppress']); + $secondMockToken->expects($this->once()) + ->method('suppress'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $chain->suppressTokens(); + } + + public function testReloadRequired() + { + $mockToken = $this->getTokenRequiringReload(true); + $secondMockToken = $this->getTokenRequiringReload(false); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertTrue($chain->reloadRequired()); + } + + public function testReloadRequiredIfError() + { + $mockToken = $this->getTokenRequiringReloadIfError(true); + $secondMockToken = $this->getTokenRequiringReloadIfError(false); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertTrue($chain->reloadRequiredIfError()); + } + + public function testParams() + { + $mockToken = $this->getTokenRequiringReload(true, ['params']); + $mockToken->expects($this->once()) + ->method('params') + ->with($this->isTrue()) + ->will($this->returnValue(['mockTokenParam' => '1'])); + $secondMockToken = $this->getTokenRequiringReload(true, ['params']); + $secondMockToken->expects($this->once()) + ->method('params') + ->with($this->isTrue()) + ->will($this->returnValue(['secondMockTokenParam' => '2'])); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertEquals(['mockTokenParam' => '1', 'secondMockTokenParam' => '2'], $chain->params(true)); + + $mockToken = $this->getTokenRequiringReload(true, ['params']); + $mockToken->expects($this->once()) + ->method('params') + ->with($this->isFalse()) + ->will($this->returnValue(['mockTokenParam' => '1'])); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $this->assertEquals(['mockTokenParam' => '1'], $chain->params(false)); + } + + public function testGetRedirectUrlBase() + { + $mockUrlToken = $this->createPartialMock(URLConfirmationToken::class, ['reloadRequired', 'getRedirectUrlBase']); + $mockUrlToken->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue(true)); + $mockUrlToken->expects($this->any()) + ->method('getRedirectUrlBase') + ->will($this->returnValue('url-base')); + + $mockParameterToken = $this->createPartialMock(ParameterConfirmationToken::class, ['reloadRequired', 'getRedirectUrlBase']); + $mockParameterToken->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue(true)); + $mockParameterToken->expects($this->any()) + ->method('getRedirectUrlBase') + ->will($this->returnValue('parameter-base')); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockParameterToken); + $chain->pushToken($mockUrlToken); + $this->assertEquals('url-base', $chain->getRedirectUrlBase(), 'URLConfirmationToken url base should take priority'); + + // Push them in reverse order to check priority still correct + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockUrlToken); + $chain->pushToken($mockParameterToken); + $this->assertEquals('url-base', $chain->getRedirectUrlBase(), 'URLConfirmationToken url base should take priority'); + } + + public function testGetRedirectUrlParams() + { + $mockToken = $this->getTokenRequiringReload(true, ['getRedirectUrlParams']); + $mockToken->expects($this->once()) + ->method('getRedirectUrlParams') + ->will($this->returnValue(['mockTokenParam' => '1'])); + + $secondMockToken = $this->getTokenRequiringReload(true, ['getRedirectUrlParams']); + $secondMockToken->expects($this->once()) + ->method('getRedirectUrlParams') + ->will($this->returnValue(['secondMockTokenParam' => '2'])); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertEquals(['mockTokenParam' => '1', 'secondMockTokenParam' => '2'], $chain->getRedirectUrlParams()); + } +} diff --git a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php index 7df6f6ebf..a90799026 100644 --- a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php +++ b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php @@ -121,4 +121,56 @@ class ErrorControlChainMiddlewareTest extends SapphireTest $this->assertNotContains('?devbuildtoken=', $location); $this->assertContains('Security/login', $location); } + + public function testLiveBuildAndFlushAdmin() + { + // Mock admin + $adminID = $this->logInWithPermission('ADMIN'); + $this->logOut(); + + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as admin + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build/', ['flush' => '1']); + $request->setSession(new Session(['loggedInAs' => $adminID])); + $result = $chain->process($request, function () { + return null; + }); + + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertContains('/dev/build', $location); + $this->assertContains('flush=1', $location); + $this->assertContains('devbuildtoken=', $location); + $this->assertContains('flushtoken=', $location); + $this->assertNotContains('Security/login', $location); + } + + public function testLiveBuildAndFlushUnauthenticated() + { + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as no one + Security::setCurrentUser(null); + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build', ['flush' => '1']); + $request->setSession(new Session(['loggedInAs' => 0])); + $result = $chain->process($request, function () { + return null; + }); + + // Should be directed to login, not to flush + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertNotContains('/dev/build', $location); + $this->assertNotContains('flush=1', $location); + $this->assertNotContains('devbuildtoken=', $location); + $this->assertNotContains('flushtoken=', $location); + $this->assertContains('Security/login', $location); + } } From af000bea9b16ea553cae7f7f662f74ab8dc343df Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Tue, 21 Aug 2018 11:20:15 +0100 Subject: [PATCH 05/17] [SS-2018-019] Add confirmation token to dev/build --- src/Control/HTTPApplication.php | 2 +- src/Core/Startup/ConfirmationToken.php | 182 ++++++++++++++++++ src/Core/Startup/ErrorControlChain.php | 3 +- .../Startup/ErrorControlChainMiddleware.php | 43 +++-- src/Core/Startup/ErrorDirector.php | 4 +- .../Startup/ParameterConfirmationToken.php | 172 +---------------- src/Core/Startup/URLConfirmationToken.php | 136 +++++++++++++ .../ErrorControlChainMiddlewareTest.php | 48 +++++ .../ParameterConfirmationTokenTest.php | 4 +- .../Core/Startup/URLConfirmationTokenTest.php | 148 ++++++++++++++ .../URLConfirmationTokenTest/StubToken.php | 27 +++ .../StubValidToken.php | 15 ++ 12 files changed, 600 insertions(+), 184 deletions(-) create mode 100644 src/Core/Startup/ConfirmationToken.php create mode 100644 src/Core/Startup/URLConfirmationToken.php create mode 100644 tests/php/Core/Startup/URLConfirmationTokenTest.php create mode 100644 tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php create mode 100644 tests/php/Core/Startup/URLConfirmationTokenTest/StubValidToken.php diff --git a/src/Control/HTTPApplication.php b/src/Control/HTTPApplication.php index 4d0f7cb9d..35f453d6d 100644 --- a/src/Control/HTTPApplication.php +++ b/src/Control/HTTPApplication.php @@ -41,7 +41,7 @@ class HTTPApplication implements Application */ public function handle(HTTPRequest $request) { - $flush = array_key_exists('flush', $request->getVars()) || strpos($request->getURL(), 'dev/build') === 0; + $flush = array_key_exists('flush', $request->getVars()) || ($request->getURL() === 'dev/build'); // Ensure boot is invoked return $this->execute($request, function (HTTPRequest $request) { diff --git a/src/Core/Startup/ConfirmationToken.php b/src/Core/Startup/ConfirmationToken.php new file mode 100644 index 000000000..d23563f46 --- /dev/null +++ b/src/Core/Startup/ConfirmationToken.php @@ -0,0 +1,182 @@ +reloadRequired() || $token->reloadRequiredIfError()) { + $token->suppress(); + $target = $token; + } + } + return $target; + } + + /** + * Generate a local filesystem path to store a token + * + * @param $token + * @return string + */ + protected function pathForToken($token) + { + return TEMP_PATH . DIRECTORY_SEPARATOR . 'token_' . preg_replace('/[^a-z0-9]+/', '', $token); + } + + /** + * Generate a new random token and store it + * + * @return string Token name + */ + protected function genToken() + { + // Generate a new random token (as random as possible) + $rg = new RandomGenerator(); + $token = $rg->randomToken('md5'); + + // Store a file in the session save path (safer than /tmp, as open_basedir might limit that) + file_put_contents($this->pathForToken($token), $token); + + return $token; + } + + /** + * Is the necessary token provided for this parameter? + * A value must be provided for the token + * + * @return bool + */ + public function tokenProvided() + { + return !empty($this->token); + } + + /** + * Validate a token + * + * @param string $token + * @return boolean True if the token is valid + */ + protected function checkToken($token) + { + if (!$token) { + return false; + } + + $file = $this->pathForToken($token); + $content = null; + + if (file_exists($file)) { + $content = file_get_contents($file); + unlink($file); + } + + return $content === $token; + } + + /** + * Get redirect url, excluding querystring + * + * @return string + */ + public function currentURL() + { + return Controller::join_links(Director::baseURL(), $this->request->getURL(false)); + } + + /** + * Forces a reload of the request with the token included + * + * @return HTTPResponse + */ + public function reloadWithToken() + { + $location = $this->redirectURL(); + $locationJS = Convert::raw2js($location); + $locationATT = Convert::raw2att($location); + $body = <<location.href='$locationJS'; + +You are being redirected. If you are not redirected soon, click here to continue +HTML; + + // Build response + $result = new HTTPResponse($body); + $result->redirect($location); + return $result; + } + + /** + * Is this parameter requested without a valid token? + * + * @return bool True if the parameter is given without a valid token + */ + abstract public function reloadRequired(); + + /** + * Check if this token is provided either in the backurl, or directly, + * but without a token + * + * @return bool + */ + abstract public function reloadRequiredIfError(); + + /** + * Suppress the current parameter for the duration of this request + */ + abstract public function suppress(); + + /** + * Determine the querystring parameters to include + * + * @param bool $includeToken Include the token value? + * @return array List of querystring parameters, possibly including token parameter + */ + abstract public function params($includeToken = true); + + /** + * Get redirection URL + * + * @return string + */ + abstract protected function redirectURL(); +} diff --git a/src/Core/Startup/ErrorControlChain.php b/src/Core/Startup/ErrorControlChain.php index f34a2c802..e2d14db65 100644 --- a/src/Core/Startup/ErrorControlChain.php +++ b/src/Core/Startup/ErrorControlChain.php @@ -15,8 +15,7 @@ use Exception; * $chain = new ErrorControlChain(); * $chain->then($callback1)->then($callback2)->thenIfErrored($callback3)->execute(); * - * WARNING: This class is experimental and designed specifically for use pre-startup. - * It will likely be heavily refactored before the release of 3.2 + * @internal This class is designed specifically for use pre-startup and may change without warning */ class ErrorControlChain { diff --git a/src/Core/Startup/ErrorControlChainMiddleware.php b/src/Core/Startup/ErrorControlChainMiddleware.php index bdb5ff0a3..e81444629 100644 --- a/src/Core/Startup/ErrorControlChainMiddleware.php +++ b/src/Core/Startup/ErrorControlChainMiddleware.php @@ -12,6 +12,8 @@ use SilverStripe\Security\Security; /** * Decorates application bootstrapping with errorcontrolchain + * + * @internal This class is designed specifically for use pre-startup and may change without warning */ class ErrorControlChainMiddleware implements HTTPMiddleware { @@ -30,27 +32,42 @@ class ErrorControlChainMiddleware implements HTTPMiddleware $this->application = $application; } + /** + * @param HTTPRequest $request + * @return ConfirmationToken|null + */ + protected function prepareConfirmationTokenIfRequired(HTTPRequest $request) + { + $token = URLConfirmationToken::prepare_tokens(['dev/build'], $request); + + if (!$token) { + $token = ParameterConfirmationToken::prepare_tokens( + ['isTest', 'isDev', 'flush'], + $request + ); + } + + return $token; + } + public function process(HTTPRequest $request, callable $next) { $result = null; // Prepare tokens and execute chain - $reloadToken = ParameterConfirmationToken::prepare_tokens( - ['isTest', 'isDev', 'flush'], - $request - ); + $confirmationToken = $this->prepareConfirmationTokenIfRequired($request); $chain = new ErrorControlChain(); $chain - ->then(function () use ($request, $chain, $reloadToken, $next, &$result) { + ->then(function () use ($request, $chain, $confirmationToken, $next, &$result) { // If no redirection is necessary then we can disable error supression - if (!$reloadToken) { + if (!$confirmationToken) { $chain->setSuppression(false); } try { // Check if a token is requesting a redirect - if ($reloadToken && $reloadToken->reloadRequired()) { - $result = $this->safeReloadWithToken($request, $reloadToken); + if ($confirmationToken && $confirmationToken->reloadRequired()) { + $result = $this->safeReloadWithToken($request, $confirmationToken); } else { // If no reload necessary, process application $result = call_user_func($next, $request); @@ -60,9 +77,9 @@ class ErrorControlChainMiddleware implements HTTPMiddleware } }) // Finally if a token was requested but there was an error while figuring out if it's allowed, do it anyway - ->thenIfErrored(function () use ($reloadToken) { - if ($reloadToken && $reloadToken->reloadRequiredIfError()) { - $result = $reloadToken->reloadWithToken(); + ->thenIfErrored(function () use ($confirmationToken) { + if ($confirmationToken && $confirmationToken->reloadRequiredIfError()) { + $result = $confirmationToken->reloadWithToken(); $result->output(); } }) @@ -85,7 +102,7 @@ class ErrorControlChainMiddleware implements HTTPMiddleware // Ensure session is started $request->getSession()->init($request); - + // Request with ErrorDirector $result = ErrorDirector::singleton()->handleRequestWithToken( $request, @@ -98,7 +115,7 @@ class ErrorControlChainMiddleware implements HTTPMiddleware // Fail and redirect the user to the login page $params = array_merge($request->getVars(), $reloadToken->params(false)); - $backURL = $request->getURL() . '?' . http_build_query($params); + $backURL = $reloadToken->currentURL() . '?' . http_build_query($params); $loginPage = Director::absoluteURL(Security::config()->get('login_url')); $loginPage .= "?BackURL=" . urlencode($backURL); $result = new HTTPResponse(); diff --git a/src/Core/Startup/ErrorDirector.php b/src/Core/Startup/ErrorDirector.php index 3c994c6af..54001fd05 100644 --- a/src/Core/Startup/ErrorDirector.php +++ b/src/Core/Startup/ErrorDirector.php @@ -21,11 +21,11 @@ class ErrorDirector extends Director * Redirect with token if allowed, or null if not allowed * * @param HTTPRequest $request - * @param ParameterConfirmationToken $token + * @param ConfirmationToken $token * @param Kernel $kernel * @return null|HTTPResponse Redirection response, or null if not able to redirect */ - public function handleRequestWithToken(HTTPRequest $request, ParameterConfirmationToken $token, Kernel $kernel) + public function handleRequestWithToken(HTTPRequest $request, ConfirmationToken $token, Kernel $kernel) { Injector::inst()->registerService($request, HTTPRequest::class); diff --git a/src/Core/Startup/ParameterConfirmationToken.php b/src/Core/Startup/ParameterConfirmationToken.php index 1c80db1d0..4e90f1ef7 100644 --- a/src/Core/Startup/ParameterConfirmationToken.php +++ b/src/Core/Startup/ParameterConfirmationToken.php @@ -9,30 +9,21 @@ use SilverStripe\Core\Convert; use SilverStripe\Security\RandomGenerator; /** - * Class ParameterConfirmationToken + * This is used to protect dangerous GET parameters that need to be detected early in the request + * lifecycle by generating a one-time-use token & redirecting with that token included in the + * redirected URL * - * When you need to use a dangerous GET parameter that needs to be set before core/Core.php is - * established, this class takes care of allowing some other code of confirming the parameter, - * by generating a one-time-use token & redirecting with that token included in the redirected URL - * - * WARNING: This class is experimental and designed specifically for use pre-startup. - * It will likely be heavily refactored before the release of 3.2 + * @internal This class is designed specifically for use pre-startup and may change without warning */ -class ParameterConfirmationToken +class ParameterConfirmationToken extends ConfirmationToken { - /** * The name of the parameter * * @var string */ protected $parameterName = null; - - /** - * @var HTTPRequest - */ - protected $request = null; - + /** * The parameter given in the main request * @@ -48,60 +39,6 @@ class ParameterConfirmationToken protected $parameterBackURL = null; /** - * The validated and checked token for this parameter - * - * @var string|null A string value, or null if either not provided or invalid - */ - protected $token = null; - - protected function pathForToken($token) - { - return TEMP_PATH . DIRECTORY_SEPARATOR . 'token_' . preg_replace('/[^a-z0-9]+/', '', $token); - } - - /** - * Generate a new random token and store it - * - * @return string Token name - */ - protected function genToken() - { - // Generate a new random token (as random as possible) - $rg = new RandomGenerator(); - $token = $rg->randomToken('md5'); - - // Store a file in the session save path (safer than /tmp, as open_basedir might limit that) - file_put_contents($this->pathForToken($token), $token); - - return $token; - } - - /** - * Validate a token - * - * @param string $token - * @return boolean True if the token is valid - */ - protected function checkToken($token) - { - if (!$token) { - return false; - } - - $file = $this->pathForToken($token); - $content = null; - - if (file_exists($file)) { - $content = file_get_contents($file); - unlink($file); - } - - return $content == $token; - } - - /** - * Create a new ParameterConfirmationToken - * * @param string $parameterName Name of the querystring parameter to check * @param HTTPRequest $request */ @@ -176,54 +113,23 @@ class ParameterConfirmationToken return $this->parameterBackURL !== null; } - /** - * Is the necessary token provided for this parameter? - * A value must be provided for the token - * - * @return bool - */ - public function tokenProvided() - { - return !empty($this->token); - } - - /** - * Is this parameter requested without a valid token? - * - * @return bool True if the parameter is given without a valid token - */ public function reloadRequired() { return $this->parameterProvided() && !$this->tokenProvided(); } - /** - * Check if this token is provided either in the backurl, or directly, - * but without a token - * - * @return bool - */ public function reloadRequiredIfError() { // Don't reload if token exists return $this->reloadRequired() || $this->existsInReferer(); } - - /** - * Suppress the current parameter by unsetting it from $_GET - */ + public function suppress() { unset($_GET[$this->parameterName]); $this->request->offsetUnset($this->parameterName); } - /** - * Determine the querystring parameters to include - * - * @param bool $includeToken Include the token value as well? - * @return array List of querystring parameters with name and token parameters - */ public function params($includeToken = true) { $params = array( @@ -234,25 +140,7 @@ class ParameterConfirmationToken } return $params; } - - /** - * Get redirect url, excluding querystring - * - * @return string - */ - protected function currentURL() - { - return Controller::join_links( - BASE_URL ?: '/', - $this->request->getURL(false) - ); - } - - /** - * Get redirection URL - * - * @return string - */ + protected function redirectURL() { // If url is encoded via BackURL, defer to home page (prevent redirect to form action) @@ -267,48 +155,4 @@ class ParameterConfirmationToken // Merge get params with current url return Controller::join_links($url, '?' . http_build_query($params)); } - - /** - * Forces a reload of the request with the token included - * - * @return HTTPResponse - */ - public function reloadWithToken() - { - $location = $this->redirectURL(); - $locationJS = Convert::raw2js($location); - $locationATT = Convert::raw2att($location); - $body = <<location.href='$locationJS'; - -You are being redirected. If you are not redirected soon, click here to continue the flush -HTML; - - // Build response - $result = new HTTPResponse($body); - $result->redirect($location); - return $result; - } - - /** - * Given a list of token names, suppress all tokens that have not been validated, and - * return the non-validated token with the highest priority - * - * @param array $keys List of token keys in ascending priority (low to high) - * @param HTTPRequest $request - * @return ParameterConfirmationToken The token container for the unvalidated $key given with the highest priority - */ - public static function prepare_tokens($keys, HTTPRequest $request) - { - $target = null; - foreach ($keys as $key) { - $token = new ParameterConfirmationToken($key, $request); - // Validate this token - if ($token->reloadRequired() || $token->reloadRequiredIfError()) { - $token->suppress(); - $target = $token; - } - } - return $target; - } } diff --git a/src/Core/Startup/URLConfirmationToken.php b/src/Core/Startup/URLConfirmationToken.php new file mode 100644 index 000000000..8176a41b8 --- /dev/null +++ b/src/Core/Startup/URLConfirmationToken.php @@ -0,0 +1,136 @@ +urlToCheck = $urlToCheck; + $this->request = $request; + $this->currentURL = $request->getURL(false); + + $this->tokenParameterName = preg_replace('/[^a-z0-9]/i', '', $urlToCheck) . 'token'; + $this->urlExistsInBackURL = $this->getURLExistsInBackURL($request); + + // If the token provided is valid, mark it as such + $token = $request->getVar($this->tokenParameterName); + if ($this->checkToken($token)) { + $this->token = $token; + } + } + + /** + * @param HTTPRequest $request + * @return bool + */ + protected function getURLExistsInBackURL(HTTPRequest $request) + { + $backURL = $request->getVar('BackURL'); + return (strpos($backURL, $this->urlToCheck) === 0); + } + + /** + * @return bool + */ + protected function urlMatches() + { + return ($this->currentURL === $this->urlToCheck); + } + + /** + * @return string + */ + public function getURLToCheck() + { + return $this->urlToCheck; + } + + /** + * @return bool + */ + public function urlExistsInBackURL() + { + return $this->urlExistsInBackURL; + } + + public function reloadRequired() + { + return $this->urlMatches() && !$this->tokenProvided(); + } + + public function reloadRequiredIfError() + { + return $this->reloadRequired() || $this->urlExistsInBackURL(); + } + + public function suppress() + { + $_SERVER['REQUEST_URI'] = '/'; + $this->request->setURL('/'); + } + + public function params($includeToken = true) + { + $params = []; + if ($includeToken) { + $params[$this->tokenParameterName] = $this->genToken(); + } + + return $params; + } + + public function currentURL() + { + return Controller::join_links(Director::baseURL(), $this->currentURL); + } + + protected function redirectURL() + { + // If url is encoded via BackURL, defer to home page (prevent redirect to form action) + if ($this->urlExistsInBackURL && !$this->urlMatches()) { + $url = BASE_URL ?: '/'; + $params = $this->params(); + } else { + $url = $this->currentURL(); + $params = array_merge($this->request->getVars(), $this->params()); + } + + // Merge get params with current url + return Controller::join_links($url, '?' . http_build_query($params)); + } +} diff --git a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php index d1e4175f8..27de7f930 100644 --- a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php +++ b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php @@ -74,4 +74,52 @@ class ErrorControlChainMiddlewareTest extends SapphireTest $this->assertNotContains('?flush=1&flushtoken=', $location); $this->assertContains('Security/login', $location); } + + public function testLiveBuildAdmin() + { + // Mock admin + $adminID = $this->logInWithPermission('ADMIN'); + $this->logOut(); + + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as admin + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build/'); + $request->setSession(new Session(['loggedInAs' => $adminID])); + $result = $chain->process($request, function () { + return null; + }); + + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertContains('/dev/build', $location); + $this->assertContains('?devbuildtoken=', $location); + $this->assertNotContains('Security/login', $location); + } + + public function testLiveBuildUnauthenticated() + { + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as no one + Security::setCurrentUser(null); + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build'); + $request->setSession(new Session(['loggedInAs' => 0])); + $result = $chain->process($request, function () { + return null; + }); + + // Should be directed to login, not to flush + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertNotContains('/dev/build', $location); + $this->assertNotContains('?devbuildtoken=', $location); + $this->assertContains('Security/login', $location); + } } diff --git a/tests/php/Core/Startup/ParameterConfirmationTokenTest.php b/tests/php/Core/Startup/ParameterConfirmationTokenTest.php index 66616433f..e28af8ea5 100644 --- a/tests/php/Core/Startup/ParameterConfirmationTokenTest.php +++ b/tests/php/Core/Startup/ParameterConfirmationTokenTest.php @@ -149,14 +149,14 @@ class ParameterConfirmationTokenTest extends SapphireTest } /** - * currentAbsoluteURL needs to handle base or url being missing, or any combination of slashes. + * currentURL needs to handle base or url being missing, or any combination of slashes. * * There should always be exactly one slash between each part in the result, and any trailing slash * should be preserved. * * @dataProvider dataProviderURLs */ - public function testCurrentAbsoluteURLHandlesSlashes($url) + public function testCurrentURLHandlesSlashes($url) { $this->request->setUrl($url); diff --git a/tests/php/Core/Startup/URLConfirmationTokenTest.php b/tests/php/Core/Startup/URLConfirmationTokenTest.php new file mode 100644 index 000000000..73b07eb13 --- /dev/null +++ b/tests/php/Core/Startup/URLConfirmationTokenTest.php @@ -0,0 +1,148 @@ + 'value']); + $validToken = new StubValidToken('token/test/url', $request); + $this->assertTrue($validToken->urlMatches()); + $this->assertFalse($validToken->urlExistsInBackURL()); + $this->assertTrue($validToken->tokenProvided()); // Actually forced to true for this test + $this->assertFalse($validToken->reloadRequired()); + $this->assertFalse($validToken->reloadRequiredIfError()); + $this->assertStringStartsWith(Controller::join_links(BASE_URL, '/', 'token/test/url'), $validToken->redirectURL()); + } + + public function testTokenWithLeadingSlashInUrl() + { + $request = new HTTPRequest('GET', '/leading/slash/url', []); + $leadingSlash = new StubToken('leading/slash/url', $request); + $this->assertTrue($leadingSlash->urlMatches()); + $this->assertFalse($leadingSlash->urlExistsInBackURL()); + $this->assertFalse($leadingSlash->tokenProvided()); + $this->assertTrue($leadingSlash->reloadRequired()); + $this->assertTrue($leadingSlash->reloadRequiredIfError()); + $this->assertContains('leading/slash/url', $leadingSlash->redirectURL()); + $this->assertContains('leadingslashurltoken', $leadingSlash->redirectURL()); + } + + public function testTokenWithTrailingSlashInUrl() + { + $request = new HTTPRequest('GET', 'trailing/slash/url/', []); + $trailingSlash = new StubToken('trailing/slash/url', $request); + $this->assertTrue($trailingSlash->urlMatches()); + $this->assertFalse($trailingSlash->urlExistsInBackURL()); + $this->assertFalse($trailingSlash->tokenProvided()); + $this->assertTrue($trailingSlash->reloadRequired()); + $this->assertTrue($trailingSlash->reloadRequiredIfError()); + $this->assertContains('trailing/slash/url', $trailingSlash->redirectURL()); + $this->assertContains('trailingslashurltoken', $trailingSlash->redirectURL()); + } + + public function testTokenWithUrlMatchedInBackUrl() + { + $request = new HTTPRequest('GET', '/', ['BackURL' => 'back/url']); + $backUrl = new StubToken('back/url', $request); + $this->assertFalse($backUrl->urlMatches()); + $this->assertTrue($backUrl->urlExistsInBackURL()); + $this->assertFalse($backUrl->tokenProvided()); + $this->assertFalse($backUrl->reloadRequired()); + $this->assertTrue($backUrl->reloadRequiredIfError()); + $home = (BASE_URL ?: '/') . '?'; + $this->assertStringStartsWith($home, $backUrl->redirectURL()); + $this->assertContains('backurltoken', $backUrl->redirectURL()); + } + + public function testUrlSuppressionWhenTokenMissing() + { + // Check suppression + $request = new HTTPRequest('GET', 'test/url', []); + $token = new StubToken('test/url', $request); + $this->assertEquals('test/url', $request->getURL(false)); + $token->suppress(); + $this->assertEquals('', $request->getURL(false)); + } + + public function testPrepareTokens() + { + $request = new HTTPRequest('GET', 'test/url', []); + $token = URLConfirmationToken::prepare_tokens( + [ + 'test/url', + 'test', + 'url' + ], + $request + ); + // Test no invalid tokens + $this->assertEquals('test/url', $token->getURLToCheck()); + $this->assertNotEquals('test/url', $request->getURL(false), 'prepare_tokens() did not suppress URL'); + } + + public function testPrepareTokensDoesntSuppressWhenNotMatched() + { + $request = new HTTPRequest('GET', 'test/url', []); + $token = URLConfirmationToken::prepare_tokens( + ['another/url'], + $request + ); + $this->assertEmpty($token); + $this->assertEquals('test/url', $request->getURL(false), 'prepare_tokens() incorrectly suppressed URL'); + } + + public function testPrepareTokensWithUrlMatchedInBackUrl() + { + // Test backurl token + $request = new HTTPRequest('GET', '/', ['BackURL' => 'back/url']); + $token = URLConfirmationToken::prepare_tokens( + [ 'back/url' ], + $request + ); + $this->assertNotEmpty($token); + $this->assertEquals('back/url', $token->getURLToCheck()); + $this->assertNotEquals('back/url', $request->getURL(false), 'prepare_tokens() did not suppress URL'); + } + + public function dataProviderURLs() + { + return [ + [''], + ['/'], + ['bar'], + ['bar/'], + ['/bar'], + ['/bar/'], + ]; + } + + /** + * currentURL needs to handle base or url being missing, or any combination of slashes. + * + * There should always be exactly one slash between each part in the result, and any trailing slash + * should be preserved. + * + * @dataProvider dataProviderURLs + */ + public function testCurrentURLHandlesSlashes($url) + { + $request = new HTTPRequest('GET', $url, []); + + $token = new StubToken( + 'another/url', + $request + ); + $expected = rtrim(Controller::join_links(BASE_URL, '/', $url), '/') ?: '/'; + $this->assertEquals($expected, $token->currentURL(), "Invalid redirect for request url $url"); + } +} diff --git a/tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php b/tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php new file mode 100644 index 000000000..ca08d3e1f --- /dev/null +++ b/tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php @@ -0,0 +1,27 @@ + Date: Mon, 30 Jul 2018 11:50:11 +1200 Subject: [PATCH 06/17] [SS-2018-018] Ignore arguments in mysqli::real_connect backtrace calls --- src/Dev/Backtrace.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Dev/Backtrace.php b/src/Dev/Backtrace.php index daceca751..648cc883f 100644 --- a/src/Dev/Backtrace.php +++ b/src/Dev/Backtrace.php @@ -26,6 +26,7 @@ class Backtrace array('PDO', '__construct'), array('mysqli', 'mysqli'), array('mysqli', 'select_db'), + array('mysqli', 'real_connect'), array('SilverStripe\\ORM\\DB', 'connect'), array('SilverStripe\\Security\\Security', 'check_default_admin'), array('SilverStripe\\Security\\Security', 'encrypt_password'), From 02ad0f44aae917283784d4e9594594285f45c27d Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Fri, 24 Aug 2018 15:36:51 +0100 Subject: [PATCH 07/17] Implement ConfirmationTokenChain to handle multiple tokens at once --- ...oken.php => AbstractConfirmationToken.php} | 12 +- src/Core/Startup/ConfirmationTokenChain.php | 178 +++++++++++++++++ .../Startup/ErrorControlChainMiddleware.php | 62 +++--- src/Core/Startup/ErrorDirector.php | 13 +- .../Startup/ParameterConfirmationToken.php | 28 +-- src/Core/Startup/URLConfirmationToken.php | 29 +-- .../Startup/ConfirmationTokenChainTest.php | 185 ++++++++++++++++++ .../ErrorControlChainMiddlewareTest.php | 52 +++++ 8 files changed, 500 insertions(+), 59 deletions(-) rename src/Core/Startup/{ConfirmationToken.php => AbstractConfirmationToken.php} (95%) create mode 100644 src/Core/Startup/ConfirmationTokenChain.php create mode 100644 tests/php/Core/Startup/ConfirmationTokenChainTest.php diff --git a/src/Core/Startup/ConfirmationToken.php b/src/Core/Startup/AbstractConfirmationToken.php similarity index 95% rename from src/Core/Startup/ConfirmationToken.php rename to src/Core/Startup/AbstractConfirmationToken.php index d23563f46..11f78b48a 100644 --- a/src/Core/Startup/ConfirmationToken.php +++ b/src/Core/Startup/AbstractConfirmationToken.php @@ -15,7 +15,7 @@ use SilverStripe\Security\RandomGenerator; * * @internal This class is designed specifically for use pre-startup and may change without warning */ -abstract class ConfirmationToken +abstract class AbstractConfirmationToken { /** * @var HTTPRequest @@ -173,6 +173,16 @@ HTML; */ abstract public function params($includeToken = true); + /** + * @return string + */ + abstract public function getRedirectUrlBase(); + + /** + * @return array + */ + abstract public function getRedirectUrlParams(); + /** * Get redirection URL * diff --git a/src/Core/Startup/ConfirmationTokenChain.php b/src/Core/Startup/ConfirmationTokenChain.php new file mode 100644 index 000000000..a47f2c4c0 --- /dev/null +++ b/src/Core/Startup/ConfirmationTokenChain.php @@ -0,0 +1,178 @@ +tokens[] = $token; + } + + /** + * Collect all tokens that require a redirect + * + * @return \Generator + */ + protected function filteredTokens() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequired() || $token->reloadRequiredIfError()) { + yield $token; + } + } + } + + /** + * @return bool + */ + public function suppressionRequired() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequired()) { + return true; + } + } + + return false; + } + + /** + * Suppress URLs & GET vars from tokens that require a redirect + */ + public function suppressTokens() + { + foreach ($this->filteredTokens() as $token) { + $token->suppress(); + } + } + + /** + * @return bool + */ + public function reloadRequired() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequired()) { + return true; + } + } + + return false; + } + + /** + * @return bool + */ + public function reloadRequiredIfError() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequiredIfError()) { + return true; + } + } + + return false; + } + + /** + * @param bool $includeToken + * @return array + */ + public function params($includeToken = true) + { + $params = []; + foreach ($this->tokens as $token) { + $params = array_merge($params, $token->params($includeToken)); + } + + return $params; + } + + /** + * Fetch the URL we want to redirect to, excluding query string parameters. This may + * be the same URL (with a token to be added outside this method), or to a different + * URL if the current one has been suppressed + * + * @return string + */ + public function getRedirectUrlBase() + { + // URLConfirmationTokens may alter the URL to suppress the URL they're protecting, + // so we need to ensure they're inspected last and therefore take priority + $tokens = iterator_to_array($this->filteredTokens(), false); + usort($tokens, function ($a, $b) { + return ($a instanceof URLConfirmationToken) ? 1 : 0; + }); + + $urlBase = Director::baseURL(); + foreach ($tokens as $token) { + $urlBase = $token->getRedirectUrlBase(); + } + + return $urlBase; + } + + /** + * Collate GET vars from all token providers that need to apply a token + * + * @return array + */ + public function getRedirectUrlParams() + { + $params = []; + foreach ($this->filteredTokens() as $token) { + $params = array_merge($params, $token->getRedirectUrlParams()); + } + + return $params; + } + + /** + * @return string + */ + protected function redirectURL() + { + $params = http_build_query($this->getRedirectUrlParams()); + return Controller::join_links($this->getRedirectUrlBase(), '?' . $params); + } + + /** + * @return HTTPResponse + */ + public function reloadWithTokens() + { + $location = $this->redirectURL(); + $locationJS = Convert::raw2js($location); + $locationATT = Convert::raw2att($location); + $body = <<location.href='$locationJS'; + +You are being redirected. If you are not redirected soon, click here to continue +HTML; + + // Build response + $result = new HTTPResponse($body); + $result->redirect($location); + return $result; + } +} diff --git a/src/Core/Startup/ErrorControlChainMiddleware.php b/src/Core/Startup/ErrorControlChainMiddleware.php index e81444629..c29878e15 100644 --- a/src/Core/Startup/ErrorControlChainMiddleware.php +++ b/src/Core/Startup/ErrorControlChainMiddleware.php @@ -34,20 +34,18 @@ class ErrorControlChainMiddleware implements HTTPMiddleware /** * @param HTTPRequest $request - * @return ConfirmationToken|null + * @return ConfirmationTokenChain */ - protected function prepareConfirmationTokenIfRequired(HTTPRequest $request) + protected function prepareConfirmationTokenChain(HTTPRequest $request) { - $token = URLConfirmationToken::prepare_tokens(['dev/build'], $request); + $chain = new ConfirmationTokenChain(); + $chain->pushToken(new URLConfirmationToken('dev/build', $request)); - if (!$token) { - $token = ParameterConfirmationToken::prepare_tokens( - ['isTest', 'isDev', 'flush'], - $request - ); + foreach (['isTest', 'isDev', 'flush'] as $parameter) { + $chain->pushToken(new ParameterConfirmationToken($parameter, $request)); } - return $token; + return $chain; } public function process(HTTPRequest $request, callable $next) @@ -55,19 +53,21 @@ class ErrorControlChainMiddleware implements HTTPMiddleware $result = null; // Prepare tokens and execute chain - $confirmationToken = $this->prepareConfirmationTokenIfRequired($request); - $chain = new ErrorControlChain(); - $chain - ->then(function () use ($request, $chain, $confirmationToken, $next, &$result) { - // If no redirection is necessary then we can disable error supression - if (!$confirmationToken) { - $chain->setSuppression(false); + $confirmationTokenChain = $this->prepareConfirmationTokenChain($request); + $errorControlChain = new ErrorControlChain(); + $errorControlChain + ->then(function () use ($request, $errorControlChain, $confirmationTokenChain, $next, &$result) { + if ($confirmationTokenChain->suppressionRequired()) { + $confirmationTokenChain->suppressTokens(); + } else { + // If no redirection is necessary then we can disable error supression + $errorControlChain->setSuppression(false); } try { // Check if a token is requesting a redirect - if ($confirmationToken && $confirmationToken->reloadRequired()) { - $result = $this->safeReloadWithToken($request, $confirmationToken); + if ($confirmationTokenChain && $confirmationTokenChain->reloadRequired()) { + $result = $this->safeReloadWithTokens($request, $confirmationTokenChain); } else { // If no reload necessary, process application $result = call_user_func($next, $request); @@ -77,10 +77,16 @@ class ErrorControlChainMiddleware implements HTTPMiddleware } }) // Finally if a token was requested but there was an error while figuring out if it's allowed, do it anyway - ->thenIfErrored(function () use ($confirmationToken) { - if ($confirmationToken && $confirmationToken->reloadRequiredIfError()) { - $result = $confirmationToken->reloadWithToken(); - $result->output(); + ->thenIfErrored(function () use ($confirmationTokenChain) { + if ($confirmationTokenChain && $confirmationTokenChain->reloadRequiredIfError()) { + try { + // Reload requires manual boot + $this->getApplication()->getKernel()->boot(false); + } finally { + // Given we're in an error state here, try to continue even if the kernel boot fails + $result = $confirmationTokenChain->reloadWithTokens(); + $result->output(); + } } }) ->execute(); @@ -92,10 +98,10 @@ class ErrorControlChainMiddleware implements HTTPMiddleware * or authentication is impossible. * * @param HTTPRequest $request - * @param ParameterConfirmationToken $reloadToken + * @param ConfirmationTokenChain $confirmationTokenChain * @return HTTPResponse */ - protected function safeReloadWithToken(HTTPRequest $request, $reloadToken) + protected function safeReloadWithTokens(HTTPRequest $request, ConfirmationTokenChain $confirmationTokenChain) { // Safe reload requires manual boot $this->getApplication()->getKernel()->boot(false); @@ -104,9 +110,9 @@ class ErrorControlChainMiddleware implements HTTPMiddleware $request->getSession()->init($request); // Request with ErrorDirector - $result = ErrorDirector::singleton()->handleRequestWithToken( + $result = ErrorDirector::singleton()->handleRequestWithTokenChain( $request, - $reloadToken, + $confirmationTokenChain, $this->getApplication()->getKernel() ); if ($result) { @@ -114,8 +120,8 @@ class ErrorControlChainMiddleware implements HTTPMiddleware } // Fail and redirect the user to the login page - $params = array_merge($request->getVars(), $reloadToken->params(false)); - $backURL = $reloadToken->currentURL() . '?' . http_build_query($params); + $params = array_merge($request->getVars(), $confirmationTokenChain->params(false)); + $backURL = $confirmationTokenChain->getRedirectUrlBase() . '?' . http_build_query($params); $loginPage = Director::absoluteURL(Security::config()->get('login_url')); $loginPage .= "?BackURL=" . urlencode($backURL); $result = new HTTPResponse(); diff --git a/src/Core/Startup/ErrorDirector.php b/src/Core/Startup/ErrorDirector.php index 54001fd05..575df7183 100644 --- a/src/Core/Startup/ErrorDirector.php +++ b/src/Core/Startup/ErrorDirector.php @@ -21,18 +21,21 @@ class ErrorDirector extends Director * Redirect with token if allowed, or null if not allowed * * @param HTTPRequest $request - * @param ConfirmationToken $token + * @param ConfirmationTokenChain $confirmationTokenChain * @param Kernel $kernel * @return null|HTTPResponse Redirection response, or null if not able to redirect */ - public function handleRequestWithToken(HTTPRequest $request, ConfirmationToken $token, Kernel $kernel) - { + public function handleRequestWithTokenChain( + HTTPRequest $request, + ConfirmationTokenChain $confirmationTokenChain, + Kernel $kernel + ) { Injector::inst()->registerService($request, HTTPRequest::class); // Next, check if we're in dev mode, or the database doesn't have any security data, or we are admin - $reload = function (HTTPRequest $request) use ($token, $kernel) { + $reload = function (HTTPRequest $request) use ($confirmationTokenChain, $kernel) { if ($kernel->getEnvironment() === Kernel::DEV || !Security::database_is_ready() || Permission::check('ADMIN')) { - return $token->reloadWithToken(); + return $confirmationTokenChain->reloadWithTokens(); } return null; }; diff --git a/src/Core/Startup/ParameterConfirmationToken.php b/src/Core/Startup/ParameterConfirmationToken.php index 4e90f1ef7..bc751a2c3 100644 --- a/src/Core/Startup/ParameterConfirmationToken.php +++ b/src/Core/Startup/ParameterConfirmationToken.php @@ -3,6 +3,7 @@ namespace SilverStripe\Core\Startup; use SilverStripe\Control\Controller; +use SilverStripe\Control\Director; use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; use SilverStripe\Core\Convert; @@ -15,7 +16,7 @@ use SilverStripe\Security\RandomGenerator; * * @internal This class is designed specifically for use pre-startup and may change without warning */ -class ParameterConfirmationToken extends ConfirmationToken +class ParameterConfirmationToken extends AbstractConfirmationToken { /** * The name of the parameter @@ -140,19 +141,22 @@ class ParameterConfirmationToken extends ConfirmationToken } return $params; } + + public function getRedirectUrlBase() + { + return ($this->existsInReferer() && !$this->parameterProvided()) ? Director::baseURL() : $this->currentURL(); + } + + public function getRedirectUrlParams() + { + return ($this->existsInReferer() && !$this->parameterProvided()) + ? $this->params() + : array_merge($this->request->getVars(), $this->params()); + } protected function redirectURL() { - // If url is encoded via BackURL, defer to home page (prevent redirect to form action) - if ($this->existsInReferer() && !$this->parameterProvided()) { - $url = BASE_URL ?: '/'; - $params = $this->params(); - } else { - $url = $this->currentURL(); - $params = array_merge($this->request->getVars(), $this->params()); - } - - // Merge get params with current url - return Controller::join_links($url, '?' . http_build_query($params)); + $query = http_build_query($this->getRedirectUrlParams()); + return Controller::join_links($this->getRedirectUrlBase(), '?' . $query); } } diff --git a/src/Core/Startup/URLConfirmationToken.php b/src/Core/Startup/URLConfirmationToken.php index 8176a41b8..bb509931e 100644 --- a/src/Core/Startup/URLConfirmationToken.php +++ b/src/Core/Startup/URLConfirmationToken.php @@ -12,7 +12,7 @@ use SilverStripe\Control\HTTPRequest; * * @internal This class is designed specifically for use pre-startup and may change without warning */ -class URLConfirmationToken extends ConfirmationToken +class URLConfirmationToken extends AbstractConfirmationToken { /** * @var string @@ -60,7 +60,7 @@ class URLConfirmationToken extends ConfirmationToken */ protected function getURLExistsInBackURL(HTTPRequest $request) { - $backURL = $request->getVar('BackURL'); + $backURL = ltrim($request->getVar('BackURL'), '/'); return (strpos($backURL, $this->urlToCheck) === 0); } @@ -119,18 +119,21 @@ class URLConfirmationToken extends ConfirmationToken return Controller::join_links(Director::baseURL(), $this->currentURL); } + public function getRedirectUrlBase() + { + return ($this->urlExistsInBackURL && !$this->urlMatches()) ? Director::baseURL() : $this->currentURL(); + } + + public function getRedirectUrlParams() + { + return ($this->urlExistsInBackURL && !$this->urlMatches()) + ? $this->params() + : array_merge($this->request->getVars(), $this->params()); + } + protected function redirectURL() { - // If url is encoded via BackURL, defer to home page (prevent redirect to form action) - if ($this->urlExistsInBackURL && !$this->urlMatches()) { - $url = BASE_URL ?: '/'; - $params = $this->params(); - } else { - $url = $this->currentURL(); - $params = array_merge($this->request->getVars(), $this->params()); - } - - // Merge get params with current url - return Controller::join_links($url, '?' . http_build_query($params)); + $query = http_build_query($this->getRedirectUrlParams()); + return Controller::join_links($this->getRedirectUrlBase(), '?' . $query); } } diff --git a/tests/php/Core/Startup/ConfirmationTokenChainTest.php b/tests/php/Core/Startup/ConfirmationTokenChainTest.php new file mode 100644 index 000000000..adb8fba36 --- /dev/null +++ b/tests/php/Core/Startup/ConfirmationTokenChainTest.php @@ -0,0 +1,185 @@ +createPartialMock(ParameterConfirmationToken::class, $methods); + $mock->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue($requiresReload)); + return $mock; + } + + protected function getTokenRequiringReloadIfError($requiresReload = true, $extraMethods = []) + { + $methods = array_merge(['reloadRequired', 'reloadRequiredIfError'], $extraMethods); + $mock = $this->createPartialMock(ParameterConfirmationToken::class, $methods); + $mock->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue(false)); + $mock->expects($this->any()) + ->method('reloadRequiredIfError') + ->will($this->returnValue($requiresReload)); + return $mock; + } + + public function testFilteredTokens() + { + $chain = new ConfirmationTokenChain(); + $chain->pushToken($tokenRequiringReload = $this->getTokenRequiringReload()); + $chain->pushToken($tokenNotRequiringReload = $this->getTokenRequiringReload(false)); + $chain->pushToken($tokenRequiringReloadIfError = $this->getTokenRequiringReloadIfError()); + $chain->pushToken($tokenNotRequiringReloadIfError = $this->getTokenRequiringReloadIfError(false)); + + $reflectionMethod = new \ReflectionMethod(ConfirmationTokenChain::class, 'filteredTokens'); + $reflectionMethod->setAccessible(true); + $tokens = iterator_to_array($reflectionMethod->invoke($chain)); + + $this->assertContains($tokenRequiringReload, $tokens, 'Token requiring a reload was not returned'); + $this->assertNotContains($tokenNotRequiringReload, $tokens, 'Token not requiring a reload was returned'); + $this->assertContains($tokenRequiringReloadIfError, $tokens, 'Token requiring a reload on error was not returned'); + $this->assertNotContains($tokenNotRequiringReloadIfError, $tokens, 'Token not requiring a reload on error was returned'); + } + + public function testSuppressionRequired() + { + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReload(false)); + $this->assertFalse($chain->suppressionRequired(), 'Suppression incorrectly marked as required'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReloadIfError(false)); + $this->assertFalse($chain->suppressionRequired(), 'Suppression incorrectly marked as required'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReload()); + $this->assertTrue($chain->suppressionRequired(), 'Suppression not marked as required'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReloadIfError()); + $this->assertFalse($chain->suppressionRequired(), 'Suppression incorrectly marked as required'); + } + + public function testSuppressTokens() + { + $mockToken = $this->getTokenRequiringReload(true, ['suppress']); + $mockToken->expects($this->once()) + ->method('suppress'); + $secondMockToken = $this->getTokenRequiringReloadIfError(true, ['suppress']); + $secondMockToken->expects($this->once()) + ->method('suppress'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $chain->suppressTokens(); + } + + public function testReloadRequired() + { + $mockToken = $this->getTokenRequiringReload(true); + $secondMockToken = $this->getTokenRequiringReload(false); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertTrue($chain->reloadRequired()); + } + + public function testReloadRequiredIfError() + { + $mockToken = $this->getTokenRequiringReloadIfError(true); + $secondMockToken = $this->getTokenRequiringReloadIfError(false); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertTrue($chain->reloadRequiredIfError()); + } + + public function testParams() + { + $mockToken = $this->getTokenRequiringReload(true, ['params']); + $mockToken->expects($this->once()) + ->method('params') + ->with($this->isTrue()) + ->will($this->returnValue(['mockTokenParam' => '1'])); + $secondMockToken = $this->getTokenRequiringReload(true, ['params']); + $secondMockToken->expects($this->once()) + ->method('params') + ->with($this->isTrue()) + ->will($this->returnValue(['secondMockTokenParam' => '2'])); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertEquals(['mockTokenParam' => '1', 'secondMockTokenParam' => '2'], $chain->params(true)); + + $mockToken = $this->getTokenRequiringReload(true, ['params']); + $mockToken->expects($this->once()) + ->method('params') + ->with($this->isFalse()) + ->will($this->returnValue(['mockTokenParam' => '1'])); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $this->assertEquals(['mockTokenParam' => '1'], $chain->params(false)); + } + + public function testGetRedirectUrlBase() + { + $mockUrlToken = $this->createPartialMock(URLConfirmationToken::class, ['reloadRequired', 'getRedirectUrlBase']); + $mockUrlToken->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue(true)); + $mockUrlToken->expects($this->any()) + ->method('getRedirectUrlBase') + ->will($this->returnValue('url-base')); + + $mockParameterToken = $this->createPartialMock(ParameterConfirmationToken::class, ['reloadRequired', 'getRedirectUrlBase']); + $mockParameterToken->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue(true)); + $mockParameterToken->expects($this->any()) + ->method('getRedirectUrlBase') + ->will($this->returnValue('parameter-base')); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockParameterToken); + $chain->pushToken($mockUrlToken); + $this->assertEquals('url-base', $chain->getRedirectUrlBase(), 'URLConfirmationToken url base should take priority'); + + // Push them in reverse order to check priority still correct + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockUrlToken); + $chain->pushToken($mockParameterToken); + $this->assertEquals('url-base', $chain->getRedirectUrlBase(), 'URLConfirmationToken url base should take priority'); + } + + public function testGetRedirectUrlParams() + { + $mockToken = $this->getTokenRequiringReload(true, ['getRedirectUrlParams']); + $mockToken->expects($this->once()) + ->method('getRedirectUrlParams') + ->will($this->returnValue(['mockTokenParam' => '1'])); + + $secondMockToken = $this->getTokenRequiringReload(true, ['getRedirectUrlParams']); + $secondMockToken->expects($this->once()) + ->method('getRedirectUrlParams') + ->will($this->returnValue(['secondMockTokenParam' => '2'])); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertEquals(['mockTokenParam' => '1', 'secondMockTokenParam' => '2'], $chain->getRedirectUrlParams()); + } +} diff --git a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php index 27de7f930..7cf793c2f 100644 --- a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php +++ b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php @@ -122,4 +122,56 @@ class ErrorControlChainMiddlewareTest extends SapphireTest $this->assertNotContains('?devbuildtoken=', $location); $this->assertContains('Security/login', $location); } + + public function testLiveBuildAndFlushAdmin() + { + // Mock admin + $adminID = $this->logInWithPermission('ADMIN'); + $this->logOut(); + + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as admin + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build/', ['flush' => '1']); + $request->setSession(new Session(['loggedInAs' => $adminID])); + $result = $chain->process($request, function () { + return null; + }); + + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertContains('/dev/build', $location); + $this->assertContains('flush=1', $location); + $this->assertContains('devbuildtoken=', $location); + $this->assertContains('flushtoken=', $location); + $this->assertNotContains('Security/login', $location); + } + + public function testLiveBuildAndFlushUnauthenticated() + { + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as no one + Security::setCurrentUser(null); + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build', ['flush' => '1']); + $request->setSession(new Session(['loggedInAs' => 0])); + $result = $chain->process($request, function () { + return null; + }); + + // Should be directed to login, not to flush + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertNotContains('/dev/build', $location); + $this->assertNotContains('flush=1', $location); + $this->assertNotContains('devbuildtoken=', $location); + $this->assertNotContains('flushtoken=', $location); + $this->assertContains('Security/login', $location); + } } From 8d7c2dafabad505d769f3774c44e0595fb1a4cd9 Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Tue, 21 Aug 2018 11:20:15 +0100 Subject: [PATCH 08/17] [SS-2018-019] Add confirmation token to dev/build --- src/Control/HTTPApplication.php | 2 +- src/Core/Startup/ConfirmationToken.php | 182 ++++++++++++++++++ src/Core/Startup/ErrorControlChain.php | 3 +- .../Startup/ErrorControlChainMiddleware.php | 43 +++-- src/Core/Startup/ErrorDirector.php | 4 +- .../Startup/ParameterConfirmationToken.php | 172 +---------------- src/Core/Startup/URLConfirmationToken.php | 136 +++++++++++++ .../ErrorControlChainMiddlewareTest.php | 48 +++++ .../ParameterConfirmationTokenTest.php | 4 +- .../Core/Startup/URLConfirmationTokenTest.php | 148 ++++++++++++++ .../URLConfirmationTokenTest/StubToken.php | 27 +++ .../StubValidToken.php | 15 ++ 12 files changed, 600 insertions(+), 184 deletions(-) create mode 100644 src/Core/Startup/ConfirmationToken.php create mode 100644 src/Core/Startup/URLConfirmationToken.php create mode 100644 tests/php/Core/Startup/URLConfirmationTokenTest.php create mode 100644 tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php create mode 100644 tests/php/Core/Startup/URLConfirmationTokenTest/StubValidToken.php diff --git a/src/Control/HTTPApplication.php b/src/Control/HTTPApplication.php index 4d0f7cb9d..35f453d6d 100644 --- a/src/Control/HTTPApplication.php +++ b/src/Control/HTTPApplication.php @@ -41,7 +41,7 @@ class HTTPApplication implements Application */ public function handle(HTTPRequest $request) { - $flush = array_key_exists('flush', $request->getVars()) || strpos($request->getURL(), 'dev/build') === 0; + $flush = array_key_exists('flush', $request->getVars()) || ($request->getURL() === 'dev/build'); // Ensure boot is invoked return $this->execute($request, function (HTTPRequest $request) { diff --git a/src/Core/Startup/ConfirmationToken.php b/src/Core/Startup/ConfirmationToken.php new file mode 100644 index 000000000..d23563f46 --- /dev/null +++ b/src/Core/Startup/ConfirmationToken.php @@ -0,0 +1,182 @@ +reloadRequired() || $token->reloadRequiredIfError()) { + $token->suppress(); + $target = $token; + } + } + return $target; + } + + /** + * Generate a local filesystem path to store a token + * + * @param $token + * @return string + */ + protected function pathForToken($token) + { + return TEMP_PATH . DIRECTORY_SEPARATOR . 'token_' . preg_replace('/[^a-z0-9]+/', '', $token); + } + + /** + * Generate a new random token and store it + * + * @return string Token name + */ + protected function genToken() + { + // Generate a new random token (as random as possible) + $rg = new RandomGenerator(); + $token = $rg->randomToken('md5'); + + // Store a file in the session save path (safer than /tmp, as open_basedir might limit that) + file_put_contents($this->pathForToken($token), $token); + + return $token; + } + + /** + * Is the necessary token provided for this parameter? + * A value must be provided for the token + * + * @return bool + */ + public function tokenProvided() + { + return !empty($this->token); + } + + /** + * Validate a token + * + * @param string $token + * @return boolean True if the token is valid + */ + protected function checkToken($token) + { + if (!$token) { + return false; + } + + $file = $this->pathForToken($token); + $content = null; + + if (file_exists($file)) { + $content = file_get_contents($file); + unlink($file); + } + + return $content === $token; + } + + /** + * Get redirect url, excluding querystring + * + * @return string + */ + public function currentURL() + { + return Controller::join_links(Director::baseURL(), $this->request->getURL(false)); + } + + /** + * Forces a reload of the request with the token included + * + * @return HTTPResponse + */ + public function reloadWithToken() + { + $location = $this->redirectURL(); + $locationJS = Convert::raw2js($location); + $locationATT = Convert::raw2att($location); + $body = <<location.href='$locationJS'; + +You are being redirected. If you are not redirected soon, click here to continue +HTML; + + // Build response + $result = new HTTPResponse($body); + $result->redirect($location); + return $result; + } + + /** + * Is this parameter requested without a valid token? + * + * @return bool True if the parameter is given without a valid token + */ + abstract public function reloadRequired(); + + /** + * Check if this token is provided either in the backurl, or directly, + * but without a token + * + * @return bool + */ + abstract public function reloadRequiredIfError(); + + /** + * Suppress the current parameter for the duration of this request + */ + abstract public function suppress(); + + /** + * Determine the querystring parameters to include + * + * @param bool $includeToken Include the token value? + * @return array List of querystring parameters, possibly including token parameter + */ + abstract public function params($includeToken = true); + + /** + * Get redirection URL + * + * @return string + */ + abstract protected function redirectURL(); +} diff --git a/src/Core/Startup/ErrorControlChain.php b/src/Core/Startup/ErrorControlChain.php index f34a2c802..e2d14db65 100644 --- a/src/Core/Startup/ErrorControlChain.php +++ b/src/Core/Startup/ErrorControlChain.php @@ -15,8 +15,7 @@ use Exception; * $chain = new ErrorControlChain(); * $chain->then($callback1)->then($callback2)->thenIfErrored($callback3)->execute(); * - * WARNING: This class is experimental and designed specifically for use pre-startup. - * It will likely be heavily refactored before the release of 3.2 + * @internal This class is designed specifically for use pre-startup and may change without warning */ class ErrorControlChain { diff --git a/src/Core/Startup/ErrorControlChainMiddleware.php b/src/Core/Startup/ErrorControlChainMiddleware.php index bdb5ff0a3..e81444629 100644 --- a/src/Core/Startup/ErrorControlChainMiddleware.php +++ b/src/Core/Startup/ErrorControlChainMiddleware.php @@ -12,6 +12,8 @@ use SilverStripe\Security\Security; /** * Decorates application bootstrapping with errorcontrolchain + * + * @internal This class is designed specifically for use pre-startup and may change without warning */ class ErrorControlChainMiddleware implements HTTPMiddleware { @@ -30,27 +32,42 @@ class ErrorControlChainMiddleware implements HTTPMiddleware $this->application = $application; } + /** + * @param HTTPRequest $request + * @return ConfirmationToken|null + */ + protected function prepareConfirmationTokenIfRequired(HTTPRequest $request) + { + $token = URLConfirmationToken::prepare_tokens(['dev/build'], $request); + + if (!$token) { + $token = ParameterConfirmationToken::prepare_tokens( + ['isTest', 'isDev', 'flush'], + $request + ); + } + + return $token; + } + public function process(HTTPRequest $request, callable $next) { $result = null; // Prepare tokens and execute chain - $reloadToken = ParameterConfirmationToken::prepare_tokens( - ['isTest', 'isDev', 'flush'], - $request - ); + $confirmationToken = $this->prepareConfirmationTokenIfRequired($request); $chain = new ErrorControlChain(); $chain - ->then(function () use ($request, $chain, $reloadToken, $next, &$result) { + ->then(function () use ($request, $chain, $confirmationToken, $next, &$result) { // If no redirection is necessary then we can disable error supression - if (!$reloadToken) { + if (!$confirmationToken) { $chain->setSuppression(false); } try { // Check if a token is requesting a redirect - if ($reloadToken && $reloadToken->reloadRequired()) { - $result = $this->safeReloadWithToken($request, $reloadToken); + if ($confirmationToken && $confirmationToken->reloadRequired()) { + $result = $this->safeReloadWithToken($request, $confirmationToken); } else { // If no reload necessary, process application $result = call_user_func($next, $request); @@ -60,9 +77,9 @@ class ErrorControlChainMiddleware implements HTTPMiddleware } }) // Finally if a token was requested but there was an error while figuring out if it's allowed, do it anyway - ->thenIfErrored(function () use ($reloadToken) { - if ($reloadToken && $reloadToken->reloadRequiredIfError()) { - $result = $reloadToken->reloadWithToken(); + ->thenIfErrored(function () use ($confirmationToken) { + if ($confirmationToken && $confirmationToken->reloadRequiredIfError()) { + $result = $confirmationToken->reloadWithToken(); $result->output(); } }) @@ -85,7 +102,7 @@ class ErrorControlChainMiddleware implements HTTPMiddleware // Ensure session is started $request->getSession()->init($request); - + // Request with ErrorDirector $result = ErrorDirector::singleton()->handleRequestWithToken( $request, @@ -98,7 +115,7 @@ class ErrorControlChainMiddleware implements HTTPMiddleware // Fail and redirect the user to the login page $params = array_merge($request->getVars(), $reloadToken->params(false)); - $backURL = $request->getURL() . '?' . http_build_query($params); + $backURL = $reloadToken->currentURL() . '?' . http_build_query($params); $loginPage = Director::absoluteURL(Security::config()->get('login_url')); $loginPage .= "?BackURL=" . urlencode($backURL); $result = new HTTPResponse(); diff --git a/src/Core/Startup/ErrorDirector.php b/src/Core/Startup/ErrorDirector.php index 3c994c6af..54001fd05 100644 --- a/src/Core/Startup/ErrorDirector.php +++ b/src/Core/Startup/ErrorDirector.php @@ -21,11 +21,11 @@ class ErrorDirector extends Director * Redirect with token if allowed, or null if not allowed * * @param HTTPRequest $request - * @param ParameterConfirmationToken $token + * @param ConfirmationToken $token * @param Kernel $kernel * @return null|HTTPResponse Redirection response, or null if not able to redirect */ - public function handleRequestWithToken(HTTPRequest $request, ParameterConfirmationToken $token, Kernel $kernel) + public function handleRequestWithToken(HTTPRequest $request, ConfirmationToken $token, Kernel $kernel) { Injector::inst()->registerService($request, HTTPRequest::class); diff --git a/src/Core/Startup/ParameterConfirmationToken.php b/src/Core/Startup/ParameterConfirmationToken.php index 1c80db1d0..4e90f1ef7 100644 --- a/src/Core/Startup/ParameterConfirmationToken.php +++ b/src/Core/Startup/ParameterConfirmationToken.php @@ -9,30 +9,21 @@ use SilverStripe\Core\Convert; use SilverStripe\Security\RandomGenerator; /** - * Class ParameterConfirmationToken + * This is used to protect dangerous GET parameters that need to be detected early in the request + * lifecycle by generating a one-time-use token & redirecting with that token included in the + * redirected URL * - * When you need to use a dangerous GET parameter that needs to be set before core/Core.php is - * established, this class takes care of allowing some other code of confirming the parameter, - * by generating a one-time-use token & redirecting with that token included in the redirected URL - * - * WARNING: This class is experimental and designed specifically for use pre-startup. - * It will likely be heavily refactored before the release of 3.2 + * @internal This class is designed specifically for use pre-startup and may change without warning */ -class ParameterConfirmationToken +class ParameterConfirmationToken extends ConfirmationToken { - /** * The name of the parameter * * @var string */ protected $parameterName = null; - - /** - * @var HTTPRequest - */ - protected $request = null; - + /** * The parameter given in the main request * @@ -48,60 +39,6 @@ class ParameterConfirmationToken protected $parameterBackURL = null; /** - * The validated and checked token for this parameter - * - * @var string|null A string value, or null if either not provided or invalid - */ - protected $token = null; - - protected function pathForToken($token) - { - return TEMP_PATH . DIRECTORY_SEPARATOR . 'token_' . preg_replace('/[^a-z0-9]+/', '', $token); - } - - /** - * Generate a new random token and store it - * - * @return string Token name - */ - protected function genToken() - { - // Generate a new random token (as random as possible) - $rg = new RandomGenerator(); - $token = $rg->randomToken('md5'); - - // Store a file in the session save path (safer than /tmp, as open_basedir might limit that) - file_put_contents($this->pathForToken($token), $token); - - return $token; - } - - /** - * Validate a token - * - * @param string $token - * @return boolean True if the token is valid - */ - protected function checkToken($token) - { - if (!$token) { - return false; - } - - $file = $this->pathForToken($token); - $content = null; - - if (file_exists($file)) { - $content = file_get_contents($file); - unlink($file); - } - - return $content == $token; - } - - /** - * Create a new ParameterConfirmationToken - * * @param string $parameterName Name of the querystring parameter to check * @param HTTPRequest $request */ @@ -176,54 +113,23 @@ class ParameterConfirmationToken return $this->parameterBackURL !== null; } - /** - * Is the necessary token provided for this parameter? - * A value must be provided for the token - * - * @return bool - */ - public function tokenProvided() - { - return !empty($this->token); - } - - /** - * Is this parameter requested without a valid token? - * - * @return bool True if the parameter is given without a valid token - */ public function reloadRequired() { return $this->parameterProvided() && !$this->tokenProvided(); } - /** - * Check if this token is provided either in the backurl, or directly, - * but without a token - * - * @return bool - */ public function reloadRequiredIfError() { // Don't reload if token exists return $this->reloadRequired() || $this->existsInReferer(); } - - /** - * Suppress the current parameter by unsetting it from $_GET - */ + public function suppress() { unset($_GET[$this->parameterName]); $this->request->offsetUnset($this->parameterName); } - /** - * Determine the querystring parameters to include - * - * @param bool $includeToken Include the token value as well? - * @return array List of querystring parameters with name and token parameters - */ public function params($includeToken = true) { $params = array( @@ -234,25 +140,7 @@ class ParameterConfirmationToken } return $params; } - - /** - * Get redirect url, excluding querystring - * - * @return string - */ - protected function currentURL() - { - return Controller::join_links( - BASE_URL ?: '/', - $this->request->getURL(false) - ); - } - - /** - * Get redirection URL - * - * @return string - */ + protected function redirectURL() { // If url is encoded via BackURL, defer to home page (prevent redirect to form action) @@ -267,48 +155,4 @@ class ParameterConfirmationToken // Merge get params with current url return Controller::join_links($url, '?' . http_build_query($params)); } - - /** - * Forces a reload of the request with the token included - * - * @return HTTPResponse - */ - public function reloadWithToken() - { - $location = $this->redirectURL(); - $locationJS = Convert::raw2js($location); - $locationATT = Convert::raw2att($location); - $body = <<location.href='$locationJS'; - -You are being redirected. If you are not redirected soon, click here to continue the flush -HTML; - - // Build response - $result = new HTTPResponse($body); - $result->redirect($location); - return $result; - } - - /** - * Given a list of token names, suppress all tokens that have not been validated, and - * return the non-validated token with the highest priority - * - * @param array $keys List of token keys in ascending priority (low to high) - * @param HTTPRequest $request - * @return ParameterConfirmationToken The token container for the unvalidated $key given with the highest priority - */ - public static function prepare_tokens($keys, HTTPRequest $request) - { - $target = null; - foreach ($keys as $key) { - $token = new ParameterConfirmationToken($key, $request); - // Validate this token - if ($token->reloadRequired() || $token->reloadRequiredIfError()) { - $token->suppress(); - $target = $token; - } - } - return $target; - } } diff --git a/src/Core/Startup/URLConfirmationToken.php b/src/Core/Startup/URLConfirmationToken.php new file mode 100644 index 000000000..8176a41b8 --- /dev/null +++ b/src/Core/Startup/URLConfirmationToken.php @@ -0,0 +1,136 @@ +urlToCheck = $urlToCheck; + $this->request = $request; + $this->currentURL = $request->getURL(false); + + $this->tokenParameterName = preg_replace('/[^a-z0-9]/i', '', $urlToCheck) . 'token'; + $this->urlExistsInBackURL = $this->getURLExistsInBackURL($request); + + // If the token provided is valid, mark it as such + $token = $request->getVar($this->tokenParameterName); + if ($this->checkToken($token)) { + $this->token = $token; + } + } + + /** + * @param HTTPRequest $request + * @return bool + */ + protected function getURLExistsInBackURL(HTTPRequest $request) + { + $backURL = $request->getVar('BackURL'); + return (strpos($backURL, $this->urlToCheck) === 0); + } + + /** + * @return bool + */ + protected function urlMatches() + { + return ($this->currentURL === $this->urlToCheck); + } + + /** + * @return string + */ + public function getURLToCheck() + { + return $this->urlToCheck; + } + + /** + * @return bool + */ + public function urlExistsInBackURL() + { + return $this->urlExistsInBackURL; + } + + public function reloadRequired() + { + return $this->urlMatches() && !$this->tokenProvided(); + } + + public function reloadRequiredIfError() + { + return $this->reloadRequired() || $this->urlExistsInBackURL(); + } + + public function suppress() + { + $_SERVER['REQUEST_URI'] = '/'; + $this->request->setURL('/'); + } + + public function params($includeToken = true) + { + $params = []; + if ($includeToken) { + $params[$this->tokenParameterName] = $this->genToken(); + } + + return $params; + } + + public function currentURL() + { + return Controller::join_links(Director::baseURL(), $this->currentURL); + } + + protected function redirectURL() + { + // If url is encoded via BackURL, defer to home page (prevent redirect to form action) + if ($this->urlExistsInBackURL && !$this->urlMatches()) { + $url = BASE_URL ?: '/'; + $params = $this->params(); + } else { + $url = $this->currentURL(); + $params = array_merge($this->request->getVars(), $this->params()); + } + + // Merge get params with current url + return Controller::join_links($url, '?' . http_build_query($params)); + } +} diff --git a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php index d1e4175f8..27de7f930 100644 --- a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php +++ b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php @@ -74,4 +74,52 @@ class ErrorControlChainMiddlewareTest extends SapphireTest $this->assertNotContains('?flush=1&flushtoken=', $location); $this->assertContains('Security/login', $location); } + + public function testLiveBuildAdmin() + { + // Mock admin + $adminID = $this->logInWithPermission('ADMIN'); + $this->logOut(); + + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as admin + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build/'); + $request->setSession(new Session(['loggedInAs' => $adminID])); + $result = $chain->process($request, function () { + return null; + }); + + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertContains('/dev/build', $location); + $this->assertContains('?devbuildtoken=', $location); + $this->assertNotContains('Security/login', $location); + } + + public function testLiveBuildUnauthenticated() + { + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as no one + Security::setCurrentUser(null); + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build'); + $request->setSession(new Session(['loggedInAs' => 0])); + $result = $chain->process($request, function () { + return null; + }); + + // Should be directed to login, not to flush + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertNotContains('/dev/build', $location); + $this->assertNotContains('?devbuildtoken=', $location); + $this->assertContains('Security/login', $location); + } } diff --git a/tests/php/Core/Startup/ParameterConfirmationTokenTest.php b/tests/php/Core/Startup/ParameterConfirmationTokenTest.php index 66616433f..e28af8ea5 100644 --- a/tests/php/Core/Startup/ParameterConfirmationTokenTest.php +++ b/tests/php/Core/Startup/ParameterConfirmationTokenTest.php @@ -149,14 +149,14 @@ class ParameterConfirmationTokenTest extends SapphireTest } /** - * currentAbsoluteURL needs to handle base or url being missing, or any combination of slashes. + * currentURL needs to handle base or url being missing, or any combination of slashes. * * There should always be exactly one slash between each part in the result, and any trailing slash * should be preserved. * * @dataProvider dataProviderURLs */ - public function testCurrentAbsoluteURLHandlesSlashes($url) + public function testCurrentURLHandlesSlashes($url) { $this->request->setUrl($url); diff --git a/tests/php/Core/Startup/URLConfirmationTokenTest.php b/tests/php/Core/Startup/URLConfirmationTokenTest.php new file mode 100644 index 000000000..73b07eb13 --- /dev/null +++ b/tests/php/Core/Startup/URLConfirmationTokenTest.php @@ -0,0 +1,148 @@ + 'value']); + $validToken = new StubValidToken('token/test/url', $request); + $this->assertTrue($validToken->urlMatches()); + $this->assertFalse($validToken->urlExistsInBackURL()); + $this->assertTrue($validToken->tokenProvided()); // Actually forced to true for this test + $this->assertFalse($validToken->reloadRequired()); + $this->assertFalse($validToken->reloadRequiredIfError()); + $this->assertStringStartsWith(Controller::join_links(BASE_URL, '/', 'token/test/url'), $validToken->redirectURL()); + } + + public function testTokenWithLeadingSlashInUrl() + { + $request = new HTTPRequest('GET', '/leading/slash/url', []); + $leadingSlash = new StubToken('leading/slash/url', $request); + $this->assertTrue($leadingSlash->urlMatches()); + $this->assertFalse($leadingSlash->urlExistsInBackURL()); + $this->assertFalse($leadingSlash->tokenProvided()); + $this->assertTrue($leadingSlash->reloadRequired()); + $this->assertTrue($leadingSlash->reloadRequiredIfError()); + $this->assertContains('leading/slash/url', $leadingSlash->redirectURL()); + $this->assertContains('leadingslashurltoken', $leadingSlash->redirectURL()); + } + + public function testTokenWithTrailingSlashInUrl() + { + $request = new HTTPRequest('GET', 'trailing/slash/url/', []); + $trailingSlash = new StubToken('trailing/slash/url', $request); + $this->assertTrue($trailingSlash->urlMatches()); + $this->assertFalse($trailingSlash->urlExistsInBackURL()); + $this->assertFalse($trailingSlash->tokenProvided()); + $this->assertTrue($trailingSlash->reloadRequired()); + $this->assertTrue($trailingSlash->reloadRequiredIfError()); + $this->assertContains('trailing/slash/url', $trailingSlash->redirectURL()); + $this->assertContains('trailingslashurltoken', $trailingSlash->redirectURL()); + } + + public function testTokenWithUrlMatchedInBackUrl() + { + $request = new HTTPRequest('GET', '/', ['BackURL' => 'back/url']); + $backUrl = new StubToken('back/url', $request); + $this->assertFalse($backUrl->urlMatches()); + $this->assertTrue($backUrl->urlExistsInBackURL()); + $this->assertFalse($backUrl->tokenProvided()); + $this->assertFalse($backUrl->reloadRequired()); + $this->assertTrue($backUrl->reloadRequiredIfError()); + $home = (BASE_URL ?: '/') . '?'; + $this->assertStringStartsWith($home, $backUrl->redirectURL()); + $this->assertContains('backurltoken', $backUrl->redirectURL()); + } + + public function testUrlSuppressionWhenTokenMissing() + { + // Check suppression + $request = new HTTPRequest('GET', 'test/url', []); + $token = new StubToken('test/url', $request); + $this->assertEquals('test/url', $request->getURL(false)); + $token->suppress(); + $this->assertEquals('', $request->getURL(false)); + } + + public function testPrepareTokens() + { + $request = new HTTPRequest('GET', 'test/url', []); + $token = URLConfirmationToken::prepare_tokens( + [ + 'test/url', + 'test', + 'url' + ], + $request + ); + // Test no invalid tokens + $this->assertEquals('test/url', $token->getURLToCheck()); + $this->assertNotEquals('test/url', $request->getURL(false), 'prepare_tokens() did not suppress URL'); + } + + public function testPrepareTokensDoesntSuppressWhenNotMatched() + { + $request = new HTTPRequest('GET', 'test/url', []); + $token = URLConfirmationToken::prepare_tokens( + ['another/url'], + $request + ); + $this->assertEmpty($token); + $this->assertEquals('test/url', $request->getURL(false), 'prepare_tokens() incorrectly suppressed URL'); + } + + public function testPrepareTokensWithUrlMatchedInBackUrl() + { + // Test backurl token + $request = new HTTPRequest('GET', '/', ['BackURL' => 'back/url']); + $token = URLConfirmationToken::prepare_tokens( + [ 'back/url' ], + $request + ); + $this->assertNotEmpty($token); + $this->assertEquals('back/url', $token->getURLToCheck()); + $this->assertNotEquals('back/url', $request->getURL(false), 'prepare_tokens() did not suppress URL'); + } + + public function dataProviderURLs() + { + return [ + [''], + ['/'], + ['bar'], + ['bar/'], + ['/bar'], + ['/bar/'], + ]; + } + + /** + * currentURL needs to handle base or url being missing, or any combination of slashes. + * + * There should always be exactly one slash between each part in the result, and any trailing slash + * should be preserved. + * + * @dataProvider dataProviderURLs + */ + public function testCurrentURLHandlesSlashes($url) + { + $request = new HTTPRequest('GET', $url, []); + + $token = new StubToken( + 'another/url', + $request + ); + $expected = rtrim(Controller::join_links(BASE_URL, '/', $url), '/') ?: '/'; + $this->assertEquals($expected, $token->currentURL(), "Invalid redirect for request url $url"); + } +} diff --git a/tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php b/tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php new file mode 100644 index 000000000..ca08d3e1f --- /dev/null +++ b/tests/php/Core/Startup/URLConfirmationTokenTest/StubToken.php @@ -0,0 +1,27 @@ + Date: Mon, 30 Jul 2018 11:50:11 +1200 Subject: [PATCH 09/17] [SS-2018-018] Ignore arguments in mysqli::real_connect backtrace calls --- src/Dev/Backtrace.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Dev/Backtrace.php b/src/Dev/Backtrace.php index 756945c52..0b61f5a1b 100644 --- a/src/Dev/Backtrace.php +++ b/src/Dev/Backtrace.php @@ -26,6 +26,7 @@ class Backtrace array('PDO', '__construct'), array('mysqli', 'mysqli'), array('mysqli', 'select_db'), + array('mysqli', 'real_connect'), array('SilverStripe\\ORM\\DB', 'connect'), array('SilverStripe\\Security\\Security', 'check_default_admin'), array('SilverStripe\\Security\\Security', 'encrypt_password'), From 11fe5b3adffd36037ed62e490a4e8bedb7b76ac9 Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Fri, 24 Aug 2018 15:36:51 +0100 Subject: [PATCH 10/17] Implement ConfirmationTokenChain to handle multiple tokens at once --- ...oken.php => AbstractConfirmationToken.php} | 12 +- src/Core/Startup/ConfirmationTokenChain.php | 178 +++++++++++++++++ .../Startup/ErrorControlChainMiddleware.php | 62 +++--- src/Core/Startup/ErrorDirector.php | 13 +- .../Startup/ParameterConfirmationToken.php | 28 +-- src/Core/Startup/URLConfirmationToken.php | 29 +-- .../Startup/ConfirmationTokenChainTest.php | 185 ++++++++++++++++++ .../ErrorControlChainMiddlewareTest.php | 52 +++++ 8 files changed, 500 insertions(+), 59 deletions(-) rename src/Core/Startup/{ConfirmationToken.php => AbstractConfirmationToken.php} (95%) create mode 100644 src/Core/Startup/ConfirmationTokenChain.php create mode 100644 tests/php/Core/Startup/ConfirmationTokenChainTest.php diff --git a/src/Core/Startup/ConfirmationToken.php b/src/Core/Startup/AbstractConfirmationToken.php similarity index 95% rename from src/Core/Startup/ConfirmationToken.php rename to src/Core/Startup/AbstractConfirmationToken.php index d23563f46..11f78b48a 100644 --- a/src/Core/Startup/ConfirmationToken.php +++ b/src/Core/Startup/AbstractConfirmationToken.php @@ -15,7 +15,7 @@ use SilverStripe\Security\RandomGenerator; * * @internal This class is designed specifically for use pre-startup and may change without warning */ -abstract class ConfirmationToken +abstract class AbstractConfirmationToken { /** * @var HTTPRequest @@ -173,6 +173,16 @@ HTML; */ abstract public function params($includeToken = true); + /** + * @return string + */ + abstract public function getRedirectUrlBase(); + + /** + * @return array + */ + abstract public function getRedirectUrlParams(); + /** * Get redirection URL * diff --git a/src/Core/Startup/ConfirmationTokenChain.php b/src/Core/Startup/ConfirmationTokenChain.php new file mode 100644 index 000000000..a47f2c4c0 --- /dev/null +++ b/src/Core/Startup/ConfirmationTokenChain.php @@ -0,0 +1,178 @@ +tokens[] = $token; + } + + /** + * Collect all tokens that require a redirect + * + * @return \Generator + */ + protected function filteredTokens() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequired() || $token->reloadRequiredIfError()) { + yield $token; + } + } + } + + /** + * @return bool + */ + public function suppressionRequired() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequired()) { + return true; + } + } + + return false; + } + + /** + * Suppress URLs & GET vars from tokens that require a redirect + */ + public function suppressTokens() + { + foreach ($this->filteredTokens() as $token) { + $token->suppress(); + } + } + + /** + * @return bool + */ + public function reloadRequired() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequired()) { + return true; + } + } + + return false; + } + + /** + * @return bool + */ + public function reloadRequiredIfError() + { + foreach ($this->tokens as $token) { + if ($token->reloadRequiredIfError()) { + return true; + } + } + + return false; + } + + /** + * @param bool $includeToken + * @return array + */ + public function params($includeToken = true) + { + $params = []; + foreach ($this->tokens as $token) { + $params = array_merge($params, $token->params($includeToken)); + } + + return $params; + } + + /** + * Fetch the URL we want to redirect to, excluding query string parameters. This may + * be the same URL (with a token to be added outside this method), or to a different + * URL if the current one has been suppressed + * + * @return string + */ + public function getRedirectUrlBase() + { + // URLConfirmationTokens may alter the URL to suppress the URL they're protecting, + // so we need to ensure they're inspected last and therefore take priority + $tokens = iterator_to_array($this->filteredTokens(), false); + usort($tokens, function ($a, $b) { + return ($a instanceof URLConfirmationToken) ? 1 : 0; + }); + + $urlBase = Director::baseURL(); + foreach ($tokens as $token) { + $urlBase = $token->getRedirectUrlBase(); + } + + return $urlBase; + } + + /** + * Collate GET vars from all token providers that need to apply a token + * + * @return array + */ + public function getRedirectUrlParams() + { + $params = []; + foreach ($this->filteredTokens() as $token) { + $params = array_merge($params, $token->getRedirectUrlParams()); + } + + return $params; + } + + /** + * @return string + */ + protected function redirectURL() + { + $params = http_build_query($this->getRedirectUrlParams()); + return Controller::join_links($this->getRedirectUrlBase(), '?' . $params); + } + + /** + * @return HTTPResponse + */ + public function reloadWithTokens() + { + $location = $this->redirectURL(); + $locationJS = Convert::raw2js($location); + $locationATT = Convert::raw2att($location); + $body = <<location.href='$locationJS'; + +You are being redirected. If you are not redirected soon, click here to continue +HTML; + + // Build response + $result = new HTTPResponse($body); + $result->redirect($location); + return $result; + } +} diff --git a/src/Core/Startup/ErrorControlChainMiddleware.php b/src/Core/Startup/ErrorControlChainMiddleware.php index e81444629..c29878e15 100644 --- a/src/Core/Startup/ErrorControlChainMiddleware.php +++ b/src/Core/Startup/ErrorControlChainMiddleware.php @@ -34,20 +34,18 @@ class ErrorControlChainMiddleware implements HTTPMiddleware /** * @param HTTPRequest $request - * @return ConfirmationToken|null + * @return ConfirmationTokenChain */ - protected function prepareConfirmationTokenIfRequired(HTTPRequest $request) + protected function prepareConfirmationTokenChain(HTTPRequest $request) { - $token = URLConfirmationToken::prepare_tokens(['dev/build'], $request); + $chain = new ConfirmationTokenChain(); + $chain->pushToken(new URLConfirmationToken('dev/build', $request)); - if (!$token) { - $token = ParameterConfirmationToken::prepare_tokens( - ['isTest', 'isDev', 'flush'], - $request - ); + foreach (['isTest', 'isDev', 'flush'] as $parameter) { + $chain->pushToken(new ParameterConfirmationToken($parameter, $request)); } - return $token; + return $chain; } public function process(HTTPRequest $request, callable $next) @@ -55,19 +53,21 @@ class ErrorControlChainMiddleware implements HTTPMiddleware $result = null; // Prepare tokens and execute chain - $confirmationToken = $this->prepareConfirmationTokenIfRequired($request); - $chain = new ErrorControlChain(); - $chain - ->then(function () use ($request, $chain, $confirmationToken, $next, &$result) { - // If no redirection is necessary then we can disable error supression - if (!$confirmationToken) { - $chain->setSuppression(false); + $confirmationTokenChain = $this->prepareConfirmationTokenChain($request); + $errorControlChain = new ErrorControlChain(); + $errorControlChain + ->then(function () use ($request, $errorControlChain, $confirmationTokenChain, $next, &$result) { + if ($confirmationTokenChain->suppressionRequired()) { + $confirmationTokenChain->suppressTokens(); + } else { + // If no redirection is necessary then we can disable error supression + $errorControlChain->setSuppression(false); } try { // Check if a token is requesting a redirect - if ($confirmationToken && $confirmationToken->reloadRequired()) { - $result = $this->safeReloadWithToken($request, $confirmationToken); + if ($confirmationTokenChain && $confirmationTokenChain->reloadRequired()) { + $result = $this->safeReloadWithTokens($request, $confirmationTokenChain); } else { // If no reload necessary, process application $result = call_user_func($next, $request); @@ -77,10 +77,16 @@ class ErrorControlChainMiddleware implements HTTPMiddleware } }) // Finally if a token was requested but there was an error while figuring out if it's allowed, do it anyway - ->thenIfErrored(function () use ($confirmationToken) { - if ($confirmationToken && $confirmationToken->reloadRequiredIfError()) { - $result = $confirmationToken->reloadWithToken(); - $result->output(); + ->thenIfErrored(function () use ($confirmationTokenChain) { + if ($confirmationTokenChain && $confirmationTokenChain->reloadRequiredIfError()) { + try { + // Reload requires manual boot + $this->getApplication()->getKernel()->boot(false); + } finally { + // Given we're in an error state here, try to continue even if the kernel boot fails + $result = $confirmationTokenChain->reloadWithTokens(); + $result->output(); + } } }) ->execute(); @@ -92,10 +98,10 @@ class ErrorControlChainMiddleware implements HTTPMiddleware * or authentication is impossible. * * @param HTTPRequest $request - * @param ParameterConfirmationToken $reloadToken + * @param ConfirmationTokenChain $confirmationTokenChain * @return HTTPResponse */ - protected function safeReloadWithToken(HTTPRequest $request, $reloadToken) + protected function safeReloadWithTokens(HTTPRequest $request, ConfirmationTokenChain $confirmationTokenChain) { // Safe reload requires manual boot $this->getApplication()->getKernel()->boot(false); @@ -104,9 +110,9 @@ class ErrorControlChainMiddleware implements HTTPMiddleware $request->getSession()->init($request); // Request with ErrorDirector - $result = ErrorDirector::singleton()->handleRequestWithToken( + $result = ErrorDirector::singleton()->handleRequestWithTokenChain( $request, - $reloadToken, + $confirmationTokenChain, $this->getApplication()->getKernel() ); if ($result) { @@ -114,8 +120,8 @@ class ErrorControlChainMiddleware implements HTTPMiddleware } // Fail and redirect the user to the login page - $params = array_merge($request->getVars(), $reloadToken->params(false)); - $backURL = $reloadToken->currentURL() . '?' . http_build_query($params); + $params = array_merge($request->getVars(), $confirmationTokenChain->params(false)); + $backURL = $confirmationTokenChain->getRedirectUrlBase() . '?' . http_build_query($params); $loginPage = Director::absoluteURL(Security::config()->get('login_url')); $loginPage .= "?BackURL=" . urlencode($backURL); $result = new HTTPResponse(); diff --git a/src/Core/Startup/ErrorDirector.php b/src/Core/Startup/ErrorDirector.php index 54001fd05..575df7183 100644 --- a/src/Core/Startup/ErrorDirector.php +++ b/src/Core/Startup/ErrorDirector.php @@ -21,18 +21,21 @@ class ErrorDirector extends Director * Redirect with token if allowed, or null if not allowed * * @param HTTPRequest $request - * @param ConfirmationToken $token + * @param ConfirmationTokenChain $confirmationTokenChain * @param Kernel $kernel * @return null|HTTPResponse Redirection response, or null if not able to redirect */ - public function handleRequestWithToken(HTTPRequest $request, ConfirmationToken $token, Kernel $kernel) - { + public function handleRequestWithTokenChain( + HTTPRequest $request, + ConfirmationTokenChain $confirmationTokenChain, + Kernel $kernel + ) { Injector::inst()->registerService($request, HTTPRequest::class); // Next, check if we're in dev mode, or the database doesn't have any security data, or we are admin - $reload = function (HTTPRequest $request) use ($token, $kernel) { + $reload = function (HTTPRequest $request) use ($confirmationTokenChain, $kernel) { if ($kernel->getEnvironment() === Kernel::DEV || !Security::database_is_ready() || Permission::check('ADMIN')) { - return $token->reloadWithToken(); + return $confirmationTokenChain->reloadWithTokens(); } return null; }; diff --git a/src/Core/Startup/ParameterConfirmationToken.php b/src/Core/Startup/ParameterConfirmationToken.php index 4e90f1ef7..bc751a2c3 100644 --- a/src/Core/Startup/ParameterConfirmationToken.php +++ b/src/Core/Startup/ParameterConfirmationToken.php @@ -3,6 +3,7 @@ namespace SilverStripe\Core\Startup; use SilverStripe\Control\Controller; +use SilverStripe\Control\Director; use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; use SilverStripe\Core\Convert; @@ -15,7 +16,7 @@ use SilverStripe\Security\RandomGenerator; * * @internal This class is designed specifically for use pre-startup and may change without warning */ -class ParameterConfirmationToken extends ConfirmationToken +class ParameterConfirmationToken extends AbstractConfirmationToken { /** * The name of the parameter @@ -140,19 +141,22 @@ class ParameterConfirmationToken extends ConfirmationToken } return $params; } + + public function getRedirectUrlBase() + { + return ($this->existsInReferer() && !$this->parameterProvided()) ? Director::baseURL() : $this->currentURL(); + } + + public function getRedirectUrlParams() + { + return ($this->existsInReferer() && !$this->parameterProvided()) + ? $this->params() + : array_merge($this->request->getVars(), $this->params()); + } protected function redirectURL() { - // If url is encoded via BackURL, defer to home page (prevent redirect to form action) - if ($this->existsInReferer() && !$this->parameterProvided()) { - $url = BASE_URL ?: '/'; - $params = $this->params(); - } else { - $url = $this->currentURL(); - $params = array_merge($this->request->getVars(), $this->params()); - } - - // Merge get params with current url - return Controller::join_links($url, '?' . http_build_query($params)); + $query = http_build_query($this->getRedirectUrlParams()); + return Controller::join_links($this->getRedirectUrlBase(), '?' . $query); } } diff --git a/src/Core/Startup/URLConfirmationToken.php b/src/Core/Startup/URLConfirmationToken.php index 8176a41b8..bb509931e 100644 --- a/src/Core/Startup/URLConfirmationToken.php +++ b/src/Core/Startup/URLConfirmationToken.php @@ -12,7 +12,7 @@ use SilverStripe\Control\HTTPRequest; * * @internal This class is designed specifically for use pre-startup and may change without warning */ -class URLConfirmationToken extends ConfirmationToken +class URLConfirmationToken extends AbstractConfirmationToken { /** * @var string @@ -60,7 +60,7 @@ class URLConfirmationToken extends ConfirmationToken */ protected function getURLExistsInBackURL(HTTPRequest $request) { - $backURL = $request->getVar('BackURL'); + $backURL = ltrim($request->getVar('BackURL'), '/'); return (strpos($backURL, $this->urlToCheck) === 0); } @@ -119,18 +119,21 @@ class URLConfirmationToken extends ConfirmationToken return Controller::join_links(Director::baseURL(), $this->currentURL); } + public function getRedirectUrlBase() + { + return ($this->urlExistsInBackURL && !$this->urlMatches()) ? Director::baseURL() : $this->currentURL(); + } + + public function getRedirectUrlParams() + { + return ($this->urlExistsInBackURL && !$this->urlMatches()) + ? $this->params() + : array_merge($this->request->getVars(), $this->params()); + } + protected function redirectURL() { - // If url is encoded via BackURL, defer to home page (prevent redirect to form action) - if ($this->urlExistsInBackURL && !$this->urlMatches()) { - $url = BASE_URL ?: '/'; - $params = $this->params(); - } else { - $url = $this->currentURL(); - $params = array_merge($this->request->getVars(), $this->params()); - } - - // Merge get params with current url - return Controller::join_links($url, '?' . http_build_query($params)); + $query = http_build_query($this->getRedirectUrlParams()); + return Controller::join_links($this->getRedirectUrlBase(), '?' . $query); } } diff --git a/tests/php/Core/Startup/ConfirmationTokenChainTest.php b/tests/php/Core/Startup/ConfirmationTokenChainTest.php new file mode 100644 index 000000000..adb8fba36 --- /dev/null +++ b/tests/php/Core/Startup/ConfirmationTokenChainTest.php @@ -0,0 +1,185 @@ +createPartialMock(ParameterConfirmationToken::class, $methods); + $mock->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue($requiresReload)); + return $mock; + } + + protected function getTokenRequiringReloadIfError($requiresReload = true, $extraMethods = []) + { + $methods = array_merge(['reloadRequired', 'reloadRequiredIfError'], $extraMethods); + $mock = $this->createPartialMock(ParameterConfirmationToken::class, $methods); + $mock->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue(false)); + $mock->expects($this->any()) + ->method('reloadRequiredIfError') + ->will($this->returnValue($requiresReload)); + return $mock; + } + + public function testFilteredTokens() + { + $chain = new ConfirmationTokenChain(); + $chain->pushToken($tokenRequiringReload = $this->getTokenRequiringReload()); + $chain->pushToken($tokenNotRequiringReload = $this->getTokenRequiringReload(false)); + $chain->pushToken($tokenRequiringReloadIfError = $this->getTokenRequiringReloadIfError()); + $chain->pushToken($tokenNotRequiringReloadIfError = $this->getTokenRequiringReloadIfError(false)); + + $reflectionMethod = new \ReflectionMethod(ConfirmationTokenChain::class, 'filteredTokens'); + $reflectionMethod->setAccessible(true); + $tokens = iterator_to_array($reflectionMethod->invoke($chain)); + + $this->assertContains($tokenRequiringReload, $tokens, 'Token requiring a reload was not returned'); + $this->assertNotContains($tokenNotRequiringReload, $tokens, 'Token not requiring a reload was returned'); + $this->assertContains($tokenRequiringReloadIfError, $tokens, 'Token requiring a reload on error was not returned'); + $this->assertNotContains($tokenNotRequiringReloadIfError, $tokens, 'Token not requiring a reload on error was returned'); + } + + public function testSuppressionRequired() + { + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReload(false)); + $this->assertFalse($chain->suppressionRequired(), 'Suppression incorrectly marked as required'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReloadIfError(false)); + $this->assertFalse($chain->suppressionRequired(), 'Suppression incorrectly marked as required'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReload()); + $this->assertTrue($chain->suppressionRequired(), 'Suppression not marked as required'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($this->getTokenRequiringReloadIfError()); + $this->assertFalse($chain->suppressionRequired(), 'Suppression incorrectly marked as required'); + } + + public function testSuppressTokens() + { + $mockToken = $this->getTokenRequiringReload(true, ['suppress']); + $mockToken->expects($this->once()) + ->method('suppress'); + $secondMockToken = $this->getTokenRequiringReloadIfError(true, ['suppress']); + $secondMockToken->expects($this->once()) + ->method('suppress'); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $chain->suppressTokens(); + } + + public function testReloadRequired() + { + $mockToken = $this->getTokenRequiringReload(true); + $secondMockToken = $this->getTokenRequiringReload(false); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertTrue($chain->reloadRequired()); + } + + public function testReloadRequiredIfError() + { + $mockToken = $this->getTokenRequiringReloadIfError(true); + $secondMockToken = $this->getTokenRequiringReloadIfError(false); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertTrue($chain->reloadRequiredIfError()); + } + + public function testParams() + { + $mockToken = $this->getTokenRequiringReload(true, ['params']); + $mockToken->expects($this->once()) + ->method('params') + ->with($this->isTrue()) + ->will($this->returnValue(['mockTokenParam' => '1'])); + $secondMockToken = $this->getTokenRequiringReload(true, ['params']); + $secondMockToken->expects($this->once()) + ->method('params') + ->with($this->isTrue()) + ->will($this->returnValue(['secondMockTokenParam' => '2'])); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertEquals(['mockTokenParam' => '1', 'secondMockTokenParam' => '2'], $chain->params(true)); + + $mockToken = $this->getTokenRequiringReload(true, ['params']); + $mockToken->expects($this->once()) + ->method('params') + ->with($this->isFalse()) + ->will($this->returnValue(['mockTokenParam' => '1'])); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $this->assertEquals(['mockTokenParam' => '1'], $chain->params(false)); + } + + public function testGetRedirectUrlBase() + { + $mockUrlToken = $this->createPartialMock(URLConfirmationToken::class, ['reloadRequired', 'getRedirectUrlBase']); + $mockUrlToken->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue(true)); + $mockUrlToken->expects($this->any()) + ->method('getRedirectUrlBase') + ->will($this->returnValue('url-base')); + + $mockParameterToken = $this->createPartialMock(ParameterConfirmationToken::class, ['reloadRequired', 'getRedirectUrlBase']); + $mockParameterToken->expects($this->any()) + ->method('reloadRequired') + ->will($this->returnValue(true)); + $mockParameterToken->expects($this->any()) + ->method('getRedirectUrlBase') + ->will($this->returnValue('parameter-base')); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockParameterToken); + $chain->pushToken($mockUrlToken); + $this->assertEquals('url-base', $chain->getRedirectUrlBase(), 'URLConfirmationToken url base should take priority'); + + // Push them in reverse order to check priority still correct + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockUrlToken); + $chain->pushToken($mockParameterToken); + $this->assertEquals('url-base', $chain->getRedirectUrlBase(), 'URLConfirmationToken url base should take priority'); + } + + public function testGetRedirectUrlParams() + { + $mockToken = $this->getTokenRequiringReload(true, ['getRedirectUrlParams']); + $mockToken->expects($this->once()) + ->method('getRedirectUrlParams') + ->will($this->returnValue(['mockTokenParam' => '1'])); + + $secondMockToken = $this->getTokenRequiringReload(true, ['getRedirectUrlParams']); + $secondMockToken->expects($this->once()) + ->method('getRedirectUrlParams') + ->will($this->returnValue(['secondMockTokenParam' => '2'])); + + $chain = new ConfirmationTokenChain(); + $chain->pushToken($mockToken); + $chain->pushToken($secondMockToken); + $this->assertEquals(['mockTokenParam' => '1', 'secondMockTokenParam' => '2'], $chain->getRedirectUrlParams()); + } +} diff --git a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php index 27de7f930..7cf793c2f 100644 --- a/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php +++ b/tests/php/Core/Startup/ErrorControlChainMiddlewareTest.php @@ -122,4 +122,56 @@ class ErrorControlChainMiddlewareTest extends SapphireTest $this->assertNotContains('?devbuildtoken=', $location); $this->assertContains('Security/login', $location); } + + public function testLiveBuildAndFlushAdmin() + { + // Mock admin + $adminID = $this->logInWithPermission('ADMIN'); + $this->logOut(); + + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as admin + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build/', ['flush' => '1']); + $request->setSession(new Session(['loggedInAs' => $adminID])); + $result = $chain->process($request, function () { + return null; + }); + + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertContains('/dev/build', $location); + $this->assertContains('flush=1', $location); + $this->assertContains('devbuildtoken=', $location); + $this->assertContains('flushtoken=', $location); + $this->assertNotContains('Security/login', $location); + } + + public function testLiveBuildAndFlushUnauthenticated() + { + // Mock app + $app = new HTTPApplication(new BlankKernel(BASE_PATH)); + $app->getKernel()->setEnvironment(Kernel::LIVE); + + // Test being logged in as no one + Security::setCurrentUser(null); + $chain = new ErrorControlChainMiddleware($app); + $request = new HTTPRequest('GET', '/dev/build', ['flush' => '1']); + $request->setSession(new Session(['loggedInAs' => 0])); + $result = $chain->process($request, function () { + return null; + }); + + // Should be directed to login, not to flush + $this->assertInstanceOf(HTTPResponse::class, $result); + $location = $result->getHeader('Location'); + $this->assertNotContains('/dev/build', $location); + $this->assertNotContains('flush=1', $location); + $this->assertNotContains('devbuildtoken=', $location); + $this->assertNotContains('flushtoken=', $location); + $this->assertContains('Security/login', $location); + } } From 74de2ce3b7d6132043ffb7238761a5fe2016f507 Mon Sep 17 00:00:00 2001 From: Aaron Carlino Date: Wed, 7 Nov 2018 17:57:45 +1300 Subject: [PATCH 11/17] Update translations --- lang/ar.yml | 3 - lang/bg.yml | 3 - lang/cs.yml | 3 - lang/da.yml | 325 ++++++++++++++++++++++++++++++++++++++++++- lang/de.yml | 3 - lang/eo.yml | 9 +- lang/es.yml | 3 - lang/et_EE.yml | 3 - lang/fa_IR.yml | 1 - lang/fi.yml | 17 ++- lang/fr.yml | 6 - lang/id.yml | 3 - lang/id_ID.yml | 3 - lang/it.yml | 15 +- lang/ja.yml | 3 - lang/lt.yml | 3 - lang/mi.yml | 3 - lang/nb.yml | 3 - lang/nl.yml | 160 ++++++++++++++++++++- lang/pl.yml | 6 - lang/ru.yml | 3 - lang/sk.yml | 3 - lang/sl.yml | 3 - lang/sr.yml | 3 - lang/sr@latin.yml | 3 - lang/sr_RS.yml | 3 - lang/sr_RS@latin.yml | 3 - lang/sv.yml | 19 ++- lang/zh.yml | 3 - 29 files changed, 530 insertions(+), 88 deletions(-) diff --git a/lang/ar.yml b/lang/ar.yml index 19381589f..518bf1344 100644 --- a/lang/ar.yml +++ b/lang/ar.yml @@ -150,7 +150,4 @@ ar: LOGIN: دخول LOSTPASSWORDHEADER: 'كلمة مرور مفقودة' NOTEPAGESECURED: 'هذه الصفحة محمية بكلمة مرور ، أدخل بيانات دخولك بالأسفل ليتم السماح لك بالوصول للصفحة' - NOTERESETLINKINVALID: "

رابط إعادة تعيين كلمة المرور غير صحيح أو نفذت صلاحيته.

\n

\nيمكنك طلب رابط جديد <\"{a href=\"{link1\"> هنا \n أو تغيير كلمة المرور الخاصة بك بعد <\"{a href=\"{link2\"> تسجيل دخولك.\n

" NOTERESETPASSWORD: 'أدخل بريدك الإلكتروني و سيتم إرسال رابط إعادة تهيئة كلمة المرور ' - PASSWORDSENTHEADER: 'رابط استعادة كلمة المرور تم إرساله إلى ''{بريدك}''' - PASSWORDSENTTEXT: 'شكرا لك! تم إرسال رابط إعادة تعيين إلى ''{بريدك}''، بشرط وجود حساب قائم بالنسبة لعنوان هذا البريد الإلكتروني .' diff --git a/lang/bg.yml b/lang/bg.yml index 3e1eba6a0..241841f1e 100644 --- a/lang/bg.yml +++ b/lang/bg.yml @@ -313,7 +313,4 @@ bg: LOGOUT: Изход LOSTPASSWORDHEADER: 'Забравена парола' NOTEPAGESECURED: 'Тази страница е защитена. Въведете вашите данни по-долу, за да продължите.' - NOTERESETLINKINVALID: '

Връзката за нулиране на парола не е вярна или е просрочена.

Можете да заявите нова тук или да промените паролата си след като влезете.

' NOTERESETPASSWORD: 'Въведете вашият email адрес и ще ви изпратим линк, с който ще можете да смените паролата си' - PASSWORDSENTHEADER: 'Връзка за нулиране на парола беше изпратена на ''{email}''' - PASSWORDSENTTEXT: 'Благодарим ви! Връзка за нулиране на паролата беше изпратен на ''{email}'', ако съществува акаунт с този имейл адрес.' diff --git a/lang/cs.yml b/lang/cs.yml index 4a3cae3ab..759f0268e 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -194,7 +194,4 @@ cs: LOGIN: Přihlásit LOSTPASSWORDHEADER: 'Zapomenuté heslo' NOTEPAGESECURED: 'Tato stránka je zabezpečená. Vložte své přihlašovací údaje a my Vám zároveň pošleme práva.' - NOTERESETLINKINVALID: '

Odkaz na resetování hesla není platný nebo je prošlý.

Můžete požádat o nový zde nebo změňte své heslo až se přihlásíte.

' NOTERESETPASSWORD: 'Zadejte svou e-mailovou adresu a bude vám zaslán nulovací odkaz pro Vaše heslo' - PASSWORDSENTHEADER: 'Odkaz na resetování hesla byl odeslán na ''{email}''' - PASSWORDSENTTEXT: 'Děkujeme! Resetovací odkaz byl odeslán na ''{email}'', pokud účet existuje pro tuto emailovou adresu.' diff --git a/lang/da.yml b/lang/da.yml index 8dc512b23..3fe62969a 100644 --- a/lang/da.yml +++ b/lang/da.yml @@ -1,5 +1,328 @@ da: + SilverStripe\Admin\LeftAndMain: + VersionUnknown: ukendt + SilverStripe\AssetAdmin\Forms\UploadField: + Dimensions: Dimensioner + EDIT: Rediger + EDITINFO: 'Rediger denne fil' + REMOVE: Fjern + SilverStripe\Control\ChangePasswordEmail_ss: + CHANGEPASSWORDFOREMAIL: 'Koden for kontoen med email addressen {email} er ændret. Hvis du ikke har skiftet din kode, så skift venligst din kode ved at klikke på linket herunder' + CHANGEPASSWORDTEXT1: 'Du skiftede dit kodeord for' + CHANGEPASSWORDTEXT3: 'Skift kodeord' + HELLO: Hej + SilverStripe\Control\Email\ForgotPasswordEmail_ss: + HELLO: Hej + TEXT1: 'Her er din' + TEXT2: 'link til at nulstille dit kodeord' + TEXT3: for + SilverStripe\Control\RequestProcessor: + INVALID_REQUEST: 'Ugyldig forespørgsel' + REQUEST_ABORTED: 'Forespørgsel annulleret' + SilverStripe\Core\Manifest\VersionProvider: + VERSIONUNKNOWN: Ukendt + SilverStripe\Forms\CheckboxField: + NOANSWER: Nej + YESANSWER: Ja + SilverStripe\Forms\CheckboxSetField_ss: + NOOPTIONSAVAILABLE: 'Ingen tilgængelige muligheder' + SilverStripe\Forms\ConfirmedPasswordField: + ATLEAST: 'Kodeord skal være mindst {min} tegn lang.' + BETWEEN: 'Kodeord skal være {min} til {max} karakterer lang.' + CURRENT_PASSWORD_ERROR: 'Det nuværende kodeord du har indtastet er ikke korrekt.' + CURRENT_PASSWORD_MISSING: 'Du skal indtaste dit nuværende kodeord.' + LOGGED_IN_ERROR: 'Du skal være logget ind for at skifte dit kodeord.' + MAXIMUM: 'Kodeord må maks være {max} tegn lang' + SHOWONCLICKTITLE: 'Skift kodeord' + SilverStripe\Forms\CurrencyField: + CURRENCYSYMBOL: DKK + SilverStripe\Forms\DateField: + VALIDDATEFORMAT2: 'Indtats venligst et gyldigt datoformat ({format})' + VALIDDATEMAXDATE: 'Din dato skal være ældre end eller matche den maksimalt tilladte dato ({date})' + VALIDDATEMINDATE: 'Din dato skal være yngre end eller matche den minimum tilladte dato ({date})' + SilverStripe\Forms\DatetimeField: + VALIDDATEMAXDATETIME: 'Din dato skal være ældre end eller matche den maksimalt tilladte dato ({datetime})' + VALIDDATETIMEFORMAT: 'Indtats venligst et gyldigt dato- og tidsformat ({format})' + VALIDDATETIMEMINDATE: 'Din dato skal være yngre end eller matche den minimum tilladte dato og tid ({datetime})' + SilverStripe\Forms\DropdownField: + CHOOSE: (Vælg) + CHOOSE_MODEL: '(Vælg {name})' + SOURCE_VALIDATION: 'Venligst vælg en eksisterende værdi fra listen. {value} er ikke en tilladt mulighed' + SilverStripe\Forms\EmailField: + VALIDATION: 'Indtast venligst en emailadresse' + SilverStripe\Forms\FileUploadReceiver: + FIELDNOTSET: 'Fil information ikke fundet' + SilverStripe\Forms\Form: + BAD_METHOD: 'Denne form kræver en {method} indsendelse' + CSRF_EXPIRED_MESSAGE: 'Din session er udløbet. Venligst gensend formularen.' + CSRF_FAILED_MESSAGE: 'Det ser ud til der har været et teknisk problem. Klik venligst på tilbageknappen, tryk opdater i din browser og prøv igen.' + VALIDATIONPASSWORDSDONTMATCH: 'Kodeordene er ikke identiske' + VALIDATIONPASSWORDSNOTEMPTY: 'Kodeord kan ikke være tomme' + VALIDATIONSTRONGPASSWORD: 'Kodeord skal mindst have et tal og et alfanumerisk tegn' + VALIDATOR: Validering + VALIDCURRENCY: 'Indtast venligst en gyldig valuta' + SilverStripe\Forms\FormField: + EXAMPLE: 'f.eks. {format}' + NONE: ingen + SilverStripe\Forms\FormScaffolder: + TABMAIN: Primær SilverStripe\Forms\GridField\GridField: - Filter: Filter + Add: 'Tilføj {name}' + CSVEXPORT: 'Eksporter til CSV' + CSVIMPORT: 'Importer CSV' + Filter: Filtrer + FilterBy: 'Filtrer på' + Find: Find + LinkExisting: 'Link eksisterende' + NewRecord: 'Ny {type}' + NoItemsFound: 'Ingen elementer fundet' + PRINTEDAT: 'Printet d.' + PRINTEDBY: 'Printet af' + PlaceHolder: 'Find {type}' + PlaceHolderWithLabels: 'Find {type} på {name}' + Print: Print + RelationSearch: Relationssøgning + ResetFilter: Nulstil + SilverStripe\Forms\GridField\GridFieldDeleteAction: + Delete: Slet + DeletePermissionsFailure: 'Ingen slette rettigheder' + EditPermissionsFailure: 'Ingen rettighed til at fjerne emnet' + UnlinkRelation: Fjern + SilverStripe\Forms\GridField\GridFieldDetailForm: + CancelBtn: Annuller + Create: Opret + Delete: Slet + DeletePermissionsFailure: 'Ingen slette rettigheder' + Deleted: 'Slet {type} {name}' + Save: Gem + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Rediger + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Kan ikke fjerne dig selv fra denne gruppe, du vil miste administrator rettigheder' + SilverStripe\Forms\GridField\GridFieldPaginator: + OF: af + Page: Side + View: Vis + SilverStripe\Forms\MoneyField: + FIELDLABELAMOUNT: Beløb + FIELDLABELCURRENCY: Valuta + INVALID_CURRENCY: 'Valuta {currency} er ikke i listen over tilladte valutaer' + SilverStripe\Forms\MultiSelectField: + SOURCE_VALIDATION: 'Vælg venligst eksisterende værdier fra listen. Ugyldig mulighed(er) {value} valgt' + SilverStripe\Forms\NullableField: + IsNullLabel: 'Er Null' + SilverStripe\Forms\NumericField: + VALIDATION: '''{value}'' er ikke et tal, kun tal accepteres i dette felt' + SilverStripe\Forms\TimeField: + VALIDATEFORMAT: 'Indtats venligst et gyldigt tidsformat ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: Dataobjekter + PLURALS: + one: 'Et dataobjekt' + other: '{count} dataobjekter' + SINGULARNAME: Dataobjekt + SilverStripe\ORM\FieldType\DBBoolean: + ANY: Enhver + NOANSWER: Nej + YESANSWER: Ja + SilverStripe\ORM\FieldType\DBDate: + DAYS_SHORT_PLURALS: + one: '{count} dag' + other: '{count} dage' + HOURS_SHORT_PLURALS: + one: '{count} time' + other: '{count} timer' + LessThanMinuteAgo: 'mindre end et minut' + MINUTES_SHORT_PLURALS: + one: '{count} minut' + other: '{count} minutter' + MONTHS_SHORT_PLURALS: + one: '{count} måned' + other: '{count} måneder' + SECONDS_SHORT_PLURALS: + one: '{count} sekund' + other: '{count} sekunder' + TIMEDIFFAGO: '{difference} siden' + TIMEDIFFIN: 'i {difference}' + YEARS_SHORT_PLURALS: + one: '{count} år' + other: '{count} år' + SilverStripe\ORM\FieldType\DBEnum: + ANY: Enhver + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'For mange relaterede objekter; fallback felt i brug' + SilverStripe\ORM\Hierarchy: + LIMITED_TITLE: 'For mange underelementer ({count})' + SilverStripe\ORM\Hierarchy\Hierarchy: + InfiniteLoopNotAllowed: 'Uendeligt løkke fundet i "{type}" hierarkiet. Ændre venligst det overliggende element for at løse dette' + LIMITED_TITLE: 'For mange underelementer ({count})' + SilverStripe\ORM\ValidationException: + DEFAULT_ERROR: Valideringsfejl + SilverStripe\Security\BasicAuth: + ENTERINFO: 'Indtast venligst et brugernavn og kodeord.' + ERRORNOTADMIN: 'Den bruger er ikke en administrator.' + ERRORNOTREC: 'Brugernavn / kodeord kunne ikke genkendes' + SilverStripe\Security\CMSMemberLoginForm: + PASSWORDEXPIRED: '

Dit kodeord er udløbet. Vælg venligst et nyt.

' + SilverStripe\Security\CMSSecurity: + INVALIDUSER: '

Ugyldig bruger. Log venligst ind igen her for at fortsætte.

' + LOGIN_MESSAGE: '

Din session er løbet ud pga. inaktivitet

' + LOGIN_TITLE: 'Log ind igen, for at fortsætte hvor du slap.' + SUCCESS: Succes + SUCCESSCONTENT: '

Logget ind. Hvis du ikke automatisk viderestilles så klik her

' + SUCCESS_TITLE: 'Logget ind med sucess' + SilverStripe\Security\DefaultAdminService: + DefaultAdminFirstname: 'Standard admin' + SilverStripe\Security\Group: + AddRole: 'Tilføj en rolle for denne gruppe' + Code: 'Gruppe kode' + DefaultGroupTitleAdministrators: Administratorer + DefaultGroupTitleContentAuthors: Indholdsforfattere + Description: Beskrivelse + GROUPNAME: Gruppenavn + GroupReminder: 'Hvis du vælger en overliggende gruppe, får denne gruppe alle dens roller' + HierarchyPermsError: 'Kan ikke tildele overliggende gruppe "{group}" med fortrinsrettigheder (kræver ADMIN adgang)' + Locked: 'Låst?' + MEMBERS: Brugere + NEWGROUP: 'Ny gruppe' + NoRoles: 'Ingen roller fundet' + PERMISSIONS: Rettigheder + PLURALNAME: Grupper + PLURALS: + one: 'En gruppe' + other: '{count} grupper' + Parent: 'Overliggende gruppe' + ROLES: Roller + ROLESDESCRIPTION: 'Roller er et prædefineret sæt af rettigheder, som kan tildeles grupper.
De bliver nedarvet fra en overliggende grupper hvis krævet.' + RolesAddEditLink: 'Administrer roller' + SINGULARNAME: Gruppe + Sort: Sortering + has_many_Permissions: Rettigheder + many_many_Members: Brugere + SilverStripe\Security\LoginAttempt: + Email: 'Email adresse' + EmailHashed: 'Email adresse (hashed)' + IP: 'IP addresse' + PLURALNAME: Loginforsøg + PLURALS: + one: 'Et loginforsøg' + other: '{count} loginforsøg' + SINGULARNAME: 'Login forsøg' + Status: Status + SilverStripe\Security\Member: + ADDGROUP: 'Tilføj gruppe' + BUTTONCHANGEPASSWORD: 'Skift kodeord' + BUTTONLOGIN: 'Log ind' + BUTTONLOGINOTHER: 'Log ind med en anden bruger' + BUTTONLOGOUT: 'Log ud' + BUTTONLOSTPASSWORD: 'Jeg har glemt mit kodeord' + CONFIRMNEWPASSWORD: 'Bekræft nyt kodeord' + CONFIRMPASSWORD: 'Bekræft kodeord' + CURRENT_PASSWORD: 'Nuværende kodeord' + EDIT_PASSWORD: 'Nyt kodeord' + EMAIL: Email + EMPTYNEWPASSWORD: 'Det nye kodeord kan ikke være tom, prøv venligst igen' + ENTEREMAIL: 'Indtast venligst en email adresse for at få et nulstillingslink.' + ERRORLOCKEDOUT2: 'Din konto er blevet midlertidigt deaktiveret pga. for mange fejlslagne loginforsøg. Forsøg venligst igen om {count} minutter.' + ERRORNEWPASSWORD: 'Du har indtastet dit nye kodeord forskelligt, forsøg igen' + ERRORPASSWORDNOTMATCH: 'Dit nuværende kodeord matcher ikke, forsøg venligst igen' + ERRORWRONGCRED: 'De indtastede værdier ser ikke ud til at være korrekte. Forsøg venligst igen.' + FIRSTNAME: Fornavn + INTERFACELANG: 'Sprog i brugerfladen' + KEEPMESIGNEDIN: 'Hold mig logget ind' + LOGGEDINAS: 'Du er logget ind som {name}.' + NEWPASSWORD: 'Nyt kodeord' + PASSWORD: Kodeord + PASSWORDEXPIRED: 'Dit kodeord er udløbet. Vælg venligst et nyt.' + PLURALNAME: Brugere + PLURALS: + one: 'En bruger' + other: '{count} brugere' + REMEMBERME: 'Husk mig til næste gang? (i {count} dage på denne enhed)' + SINGULARNAME: Bruger + SUBJECTPASSWORDCHANGED: 'Dit kodeord er blevet ændret' + SUBJECTPASSWORDRESET: 'Link til at nulstille dit kodeord' + SURNAME: Efternavn + VALIDATIONADMINLOSTACCESS: 'Kan ikke fjerne alle admin grupper fra din profil' + ValidationIdentifierFailed: 'Kan ikke overskrive eksisterende bruger #{id} med identisk identifikator ({name} = {value}))' + WELCOMEBACK: 'Velkommen tilbage, {firstname}' + YOUROLDPASSWORD: 'Dit gamle kodeord' + belongs_many_many_Groups: Grupper + db_Locale: 'Sprog i brugerfladen' + db_LockedOutUntil: 'Låst ude indtil' + db_Password: Kodeord + db_PasswordExpiry: Kodeordsudløbsdato + SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: + AUTHENTICATORNAME: 'CMS bruger loginform' + BUTTONFORGOTPASSWORD: 'Glemt kodeord' + BUTTONLOGIN: 'Log mig ind igen' + BUTTONLOGOUT: 'Log ud' + SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: + ERRORWRONGCRED: 'De indtastede værdier ser ikke ud til at være korrekte. Forsøg venligst igen.' + NoPassword: 'Der er ikke en kode på denne bruger.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'Email og kodeord' + SilverStripe\Security\MemberPassword: + PLURALNAME: 'Bruger kodeord' + PLURALS: + one: 'Et bruger kodeord' + other: '{count} bruger kodeord' + SINGULARNAME: 'Bruger kodeord' + SilverStripe\Security\PasswordValidator: + LOWCHARSTRENGTH: 'Forøg venligst kodeordets styrke, ved at tilføje nogle af følgende tegn: {chars}' + PREVPASSWORD: 'Du har tidligere brugt dette kodeord, vælg venligst et nyt kodeord' + TOOSHORT: 'Kodeordet er for kort, det skal mindst være {minimum} eller flere tegn langt' SilverStripe\Security\Permission: + AdminGroup: Administrator + CMS_ACCESS_CATEGORY: 'CMS Adgang' CONTENT_CATEGORY: Indholdsrettigheder + FULLADMINRIGHTS: 'Fuld administrator rettighed' + FULLADMINRIGHTS_HELP: 'Indebærer og overskriver alle andre tildelte rettigheder.' + PERMISSIONS_CATEGORY: 'Roller og adgangsrettigheder' + PLURALNAME: Rettigheder + PLURALS: + one: 'En rettighed' + other: '{count} rettigheder' + SINGULARNAME: Rettighed + UserPermissionsIntro: 'Tildeling af grupper til denne bruger, ændrer de rettigheder brugeren har. Se gruppe området for rettigheds detaljer på de individuelle grupper.' + SilverStripe\Security\PermissionCheckboxSetField: + AssignedTo: 'tildelt til "{title}"' + FromGroup: 'nedarvet fra gruppen "{title}"' + FromRole: 'nedarvet fra rollen "{title}"' + FromRoleOnGroup: 'nedarvet fra rollen "{roletitle}" på gruppen "{grouptitle}"' + SilverStripe\Security\PermissionRole: + OnlyAdminCanApply: 'Kun administratorer kan tilføje' + PLURALNAME: Roller + PLURALS: + one: 'En rolle' + other: '{count} roller' + SINGULARNAME: Rolle + Title: Titel + SilverStripe\Security\PermissionRoleCode: + PLURALNAME: 'Rettigheds rolle koder' + PLURALS: + one: 'En rettigheds rolle kode' + other: '{count} rettigheds rolle koder' + PermsError: 'Kan ikke tildele koden "{code}" med fortrinsrettigheder (kræver ADMIN adgang)' + SINGULARNAME: 'Rettighed rolle kode' + SilverStripe\Security\RememberLoginHash: + PLURALNAME: 'Login hashes' + PLURALS: + one: 'Et login hash' + other: '{count} Login Hashes' + SINGULARNAME: 'Login hash' + SilverStripe\Security\Security: + ALREADYLOGGEDIN: 'Du har ikke adgang til denne side. Hvis du har en anden bruger der har adgang til denne side, kan du logge ind med denne herunder.' + BUTTONSEND: 'Send mig linket til at nulstille kodeordet' + CHANGEPASSWORDBELOW: 'Du kan ændre dit kodeord herunder.' + CHANGEPASSWORDHEADER: 'Skift dit kodeord' + CONFIRMLOGOUT: 'Klik venligst på knappen herunder, for at bekræfte at du vil logge ud.' + ENTERNEWPASSWORD: 'Indtast venligst et nyt kodeord.' + ERRORPASSWORDPERMISSION: 'Du skal være logget ind, for at kunne ændre dit kodeord!' + LOGIN: 'Log ind' + LOGOUT: 'Log ud' + LOSTPASSWORDHEADER: 'Glemt kodeord' + NOTEPAGESECURED: 'Denne side er beskyttet. Indtast dine loginoplysninger herunder for at få adgang.' + NOTERESETPASSWORD: 'Indtast din email adresse, så sender vi dig et link som du kan nulstille dit kodeord med' + PASSWORDRESETSENTHEADER: 'link til at nulstille kodeord afsendt' + PASSWORDRESETSENTTEXT: 'Tak for det. Et link til at nulstille dit kodeord er afsendt, hvis der findes en bruger med denne email adresse.' diff --git a/lang/de.yml b/lang/de.yml index 1e9f16e5e..77e2f1584 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -190,7 +190,4 @@ de: LOGIN: Anmelden LOSTPASSWORDHEADER: 'Passwort vergessen' NOTEPAGESECURED: 'Diese Seite ist geschützt. Bitte melden Sie sich an und Sie werden sofort weitergeleitet.' - NOTERESETLINKINVALID: '

Der Link zum Zurücksetzen des Passworts ist entweder nicht korrekt oder abgelaufen

Sie können einen neuen Link anfordern oder Ihr Passwort nach dem einloggen ändern.

' NOTERESETPASSWORD: 'Geben Sie Ihre E-Mail-Adresse ein und wir werden Ihnen einen Link zuschicken, mit dem Sie Ihr Passwort zurücksetzen können.' - PASSWORDSENTHEADER: 'Der Link zum Zurücksetzen des Passworts wurde an ''{email}'' gesendet' - PASSWORDSENTTEXT: 'Vielen Dank! Wenn ein Account zu der E-Mail Adresse ''{email}'' existiert, wurde eine E-Mail mit dem Link zum Zurücksetzen des Passworts verschickt.' diff --git a/lang/eo.yml b/lang/eo.yml index 59806b953..fb6b74ca9 100644 --- a/lang/eo.yml +++ b/lang/eo.yml @@ -95,6 +95,8 @@ eo: DeletePermissionsFailure: 'Mankas permeso forigi' Deleted: 'Forigita {type} {name}' Save: Konservi + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Redakti SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: UnlinkSelfFailure: 'Ne povas forigi vin el ĉi tiu grupo; vi perdus administrajn rajtojn' SilverStripe\Forms\GridField\GridFieldPaginator: @@ -147,6 +149,8 @@ eo: other: '{count} jaroj' SilverStripe\ORM\FieldType\DBEnum: ANY: Ajna + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'Tro multaj objektoj; retropaŝa kampo uzata' SilverStripe\ORM\Hierarchy: LIMITED_TITLE: 'Tro da idoj ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: @@ -319,7 +323,6 @@ eo: LOGOUT: Elsaluti LOSTPASSWORDHEADER: 'Perdis pasvorton' NOTEPAGESECURED: 'Tiu paĝo estas sekurigita. Enigu viajn akreditaĵojn sube kaj vi aliros pluen.' - NOTERESETLINKINVALID: '

La pasvorta reagorda ligilo estas malvalida aŭ finiĝis.

Vi povas peti novan ĉi tie aŭ ŝanĝi vian pasvorton post vi ensalutis.

' NOTERESETPASSWORD: 'Enigu vian retpoŝtan adreson kaj ni sendos al vi ligilon per kiu vi povas reagordi vian pasvorton' - PASSWORDSENTHEADER: 'Pasvorta reagorda ligilo sendiĝis al ''{email}''' - PASSWORDSENTTEXT: 'Dankon! Reagordita ligilo sendiĝis al ''{email}'', kondiĉe ke konto ekzistas por tiu retadreso.' + PASSWORDRESETSENTHEADER: 'Pasvorta reagorda ligilo sendiĝis' + PASSWORDRESETSENTTEXT: 'Dankon. Reagorda ligilo sendiĝis, kondiĉe ke konto ekzistas por ĉi tiu retadreso.' diff --git a/lang/es.yml b/lang/es.yml index 0009c7a4a..debd4b4a7 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -249,7 +249,4 @@ es: LOGIN: Entrar LOSTPASSWORDHEADER: '¿Contraseña Perdida?' NOTEPAGESECURED: 'Esa página está protegida. Introduzca sus datos de acreditación a continuación y lo enviaremos a ella en un momento.' - NOTERESETLINKINVALID: '

El enlace para restablecer la contraseña es inválido o ha expirado.

Usted puede solicitar uno nuevo aqui o cambiar su contraseña después de que se haya conectado.

' NOTERESETPASSWORD: 'Introduzca su dirección de e-mail, y le enviaremos un enlace, con el cual podrá restaurar su contraseña' - PASSWORDSENTHEADER: 'Un enlace para restablecer la contraseña ha sido enviado a ''{email}''' - PASSWORDSENTTEXT: 'Gracias! Un enlace para restablecer la contraseña ha sido enviado a ''{email}'', siempre que una cuenta exista para la dirección de email indicada.' diff --git a/lang/et_EE.yml b/lang/et_EE.yml index 63fc4cd5d..a8fb3b686 100644 --- a/lang/et_EE.yml +++ b/lang/et_EE.yml @@ -139,7 +139,4 @@ et_EE: ERRORPASSWORDPERMISSION: 'Pead olema sisseloginud, et parooli muuta!' LOGIN: 'Logi sisse' NOTEPAGESECURED: 'See leht on turvatud. Sisesta enda andmed allpool ja me saadame sind otse edasi' - NOTERESETLINKINVALID: '

Parooli lähtestamise link on kehtetu või aegunud.

Saate taotleda uut linki siin või muuta parooli pärast sisselogimist.

' NOTERESETPASSWORD: 'Sisesta oma email ja me saadame sulle lingi kus saad oma parooli tühistada.' - PASSWORDSENTHEADER: 'Parooli lähtestamise link saadeti aadressile ''{email}''' - PASSWORDSENTTEXT: 'Aitäh! Lähtestamislink saadeti aadressile ''{email}'' eeldusel, et selle e-posti aadressiga seotud konto on olemas.' diff --git a/lang/fa_IR.yml b/lang/fa_IR.yml index b292b25d7..b9aa0ebea 100644 --- a/lang/fa_IR.yml +++ b/lang/fa_IR.yml @@ -168,4 +168,3 @@ fa_IR: ERRORPASSWORDPERMISSION: 'جهت تغییر گذرواژه خود باید وارد شده باشید!' LOGIN: ورود LOSTPASSWORDHEADER: 'فراموشی گذرواژه' - PASSWORDSENTHEADER: 'لینک ازنوسازی گذرواژه به ''{email}'' ارسال شد' diff --git a/lang/fi.yml b/lang/fi.yml index 364762d3a..b19807225 100644 --- a/lang/fi.yml +++ b/lang/fi.yml @@ -76,6 +76,7 @@ fi: LinkExisting: 'Linkitä olemassaoleva' NewRecord: 'Uusi {type}' NoItemsFound: 'Ei kohteita' + OpenFilter: 'Avaa haku ja suodatus' PRINTEDAT: Tulostettu PRINTEDBY: Tulostaja PlaceHolder: 'Etsi {type}' @@ -95,12 +96,19 @@ fi: DeletePermissionsFailure: 'Ei oikeuksia poistamiseen' Deleted: 'Poistettiin {type} {name}' Save: Tallenna + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Muokkaa + SilverStripe\Forms\GridField\GridFieldFilterHeader: + Search: 'Haku "{name}"' + SearchFormFaliure: 'Hakulomaketta ei pystytty luomaan.' SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: UnlinkSelfFailure: 'Et voi siirtää itseäsi pois tästä ryhmästä: menettäisit pääkäyttäjän oikeudet' SilverStripe\Forms\GridField\GridFieldPaginator: OF: / Page: Sivu View: Näytä + SilverStripe\Forms\GridField\GridFieldViewButton: + VIEW: Avaa SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Määrä FIELDLABELCURRENCY: Valuutta @@ -147,6 +155,8 @@ fi: other: '{count} vuotta' SilverStripe\ORM\FieldType\DBEnum: ANY: Yhtään + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'Liian monta samaan liittyvää objektia: oletuskenttä käytössä' SilverStripe\ORM\Hierarchy: LIMITED_TITLE: 'Liian monta lapsiobjektia ({count}}' SilverStripe\ORM\Hierarchy\Hierarchy: @@ -197,6 +207,7 @@ fi: many_many_Members: Jäsenet SilverStripe\Security\LoginAttempt: Email: Sähköpostiosoite + EmailHashed: 'Sähköpostiosoite (tiivistetty)' IP: IP-osoite PLURALNAME: Kirjautumisyritykset PLURALS: @@ -255,6 +266,8 @@ fi: SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: ERRORWRONGCRED: 'Antamasi tiedot eivät näytä oikeilta. Yritä uudelleen.' NoPassword: 'Tällä käyttäjällä ei ole salasanaa' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'Sähköpostiosoite & salasana' SilverStripe\Security\MemberPassword: PLURALNAME: 'Käyttäjän salasanat' PLURALS: @@ -318,5 +331,5 @@ fi: NOTEPAGESECURED: 'Tämä sivu on suojattu. Syötä tunnistetietosi alle niin pääset eteenpäin.' NOTERESETLINKINVALID: '

Salasanan palautuslinkki on virheellinen tai vanhentunut.

Voit pyytää uuden napsauttamalla tästä tai vaihtaa salasanasi kirjautumisen jälkeen.

' NOTERESETPASSWORD: 'Syötä sähköpostiosoitteesi ja lähetämme sinulle linkin, jonka avulla saat palautettua salasanasi' - PASSWORDSENTHEADER: 'Salasanan palautuslinkki lähetettiin osoitteeseen ''{email}''' - PASSWORDSENTTEXT: 'Kiitos! Salasanan palautuslinkki lähetettiin osoitteeseen ''{email}'', joka on liitettynä tähän käyttäjätiliin.' + PASSWORDRESETSENTHEADER: 'Salasanan palautuslinkki lähetetty' + PASSWORDRESETSENTTEXT: 'Kiitos, palautuslinkki on lähetetty käyttäjätilille asetettuun sähköpostiosoitteeseen.' diff --git a/lang/fr.yml b/lang/fr.yml index 5a18188da..450cfdb87 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -84,7 +84,6 @@ fr: RelationSearch: 'Rechercher relations' ResetFilter: Réinitialiser SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Supprimer Delete: Supprimer DeletePermissionsFailure: 'Vous n’avez pas les autorisations pour supprimer' EditPermissionsFailure: 'Pas de permissions pour délier l''enregistrement' @@ -96,8 +95,6 @@ fr: DeletePermissionsFailure: 'Vous n’avez pas les autorisations pour supprimer' Deleted: '{type} {name} supprimés' Save: Enregistrer - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Éditer SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: UnlinkSelfFailure: 'Impossible de retirer votre propre profil de ce groupe, vous perdriez vos droits d''administration' SilverStripe\Forms\GridField\GridFieldPaginator: @@ -322,7 +319,4 @@ fr: LOGOUT: 'Se déconnecter' LOSTPASSWORDHEADER: 'Mot de passe oublié' NOTEPAGESECURED: 'Cette page est sécurisée. Entrez vos identifiants ci-dessous et vous pourrez y avoir accès.' - NOTERESETLINKINVALID: '

Le lien de réinitialisation du mot de passe n’est pas valide ou a expiré.

Vous pouvez en demander un nouveau en suivant ce lien ou changer de mot de passe après connexion.

' NOTERESETPASSWORD: 'Entrez votre adresse email et nous vous enverrons un lien pour modifier votre mot de passe' - PASSWORDSENTHEADER: "Lien de réinitialisation de mot de passe envoyé à «\_{email}\_»" - PASSWORDSENTTEXT: "Merci\_! Un lien de réinitialisation vient d’être envoyé à «\_{email}\_», à condition que cette adresse existe." diff --git a/lang/id.yml b/lang/id.yml index d17eac338..c9c06bbff 100644 --- a/lang/id.yml +++ b/lang/id.yml @@ -167,7 +167,4 @@ id: LOGIN: Masuk LOSTPASSWORDHEADER: 'Kata Kunci yang Terlupa' NOTEPAGESECURED: 'Laman ini diamankan. Isikan data berikut untuk dikirimkan hak akses Anda.' - NOTERESETLINKINVALID: '

Tautan penggantian kata kunci tidak valid atau sudah kadaluarsa.

Anda dapat meminta yang baru di sini atau mengganti kata kunci setelah Anda masuk.

' NOTERESETPASSWORD: 'Isikan alamat email Anda untuk mendapatkan tautan penggantian kata kunci' - PASSWORDSENTHEADER: 'Tautan penggantian kata kunci dikirimkan ke ''{email}''' - PASSWORDSENTTEXT: 'Terimakasih! Tautan reset telah dikirim ke ''{email}'', berisi informasi akun untuk alamat email ini.' diff --git a/lang/id_ID.yml b/lang/id_ID.yml index 22ebcb2e5..11d1f2bb3 100644 --- a/lang/id_ID.yml +++ b/lang/id_ID.yml @@ -166,7 +166,4 @@ id_ID: LOGIN: Masuk LOSTPASSWORDHEADER: 'Kata Kunci yang Terlupa' NOTEPAGESECURED: 'Laman ini diamankan. Isikan data berikut untuk dikirimkan hak akses Anda.' - NOTERESETLINKINVALID: '

Tautan penggantian kata kunci tidak valid atau sudah kadaluarsa.

Anda dapat meminta yang baru di sini atau mengganti kata kunci setelah Anda masuk.

' NOTERESETPASSWORD: 'Isikan alamat email Anda untuk mendapatkan tautan penggantian kata kunci' - PASSWORDSENTHEADER: 'Tautan penggantian kata kunci dikirimkan ke ''{email}''' - PASSWORDSENTTEXT: 'Terimakasih! Tautan reset telah dikirim ke ''{email}'', berisi informasi akun untuk alamat email ini.' diff --git a/lang/it.yml b/lang/it.yml index 05bf5dc83..4089faf9b 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -95,6 +95,10 @@ it: DeletePermissionsFailure: 'Non hai i permessi per eliminare' Deleted: 'Eliminato {type} {name}' Save: Salva + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Modifica + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Non è possibile rimuovere te stesso da questo gruppo, perderesti i diritti di admin' SilverStripe\Forms\GridField\GridFieldPaginator: OF: di Page: Pagina @@ -145,6 +149,8 @@ it: other: '{count} anni' SilverStripe\ORM\FieldType\DBEnum: ANY: Qualsiasi + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'Troppi oggetti correlati; campo di fallback in uso' SilverStripe\ORM\Hierarchy: LIMITED_TITLE: 'Troppi figli ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: @@ -195,6 +201,7 @@ it: many_many_Members: Membri SilverStripe\Security\LoginAttempt: Email: 'Indirizzo e-mail' + EmailHashed: 'Indirizzo email (hash)' IP: 'Indirizzo IP' PLURALNAME: 'Tentativi d''accesso' PLURALS: @@ -236,6 +243,7 @@ it: SUBJECTPASSWORDCHANGED: 'La tua password è stata cambiata' SUBJECTPASSWORDRESET: 'Link per azzerare la tua password' SURNAME: Cognome + VALIDATIONADMINLOSTACCESS: 'Non è possibile rimuovere tutti i gruppi admin dal tuo profilo' ValidationIdentifierFailed: 'Non posso sovrascrivere l''utente esistente #{id} con identificatore identico ({name} = {value}))' WELCOMEBACK: 'Bentornato, {firstname}' YOUROLDPASSWORD: 'La tua vecchia password' @@ -252,6 +260,8 @@ it: SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: ERRORWRONGCRED: 'I dettagli forniti non sembrano corretti. Per favore riprovare.' NoPassword: 'Manca la password per questo utente.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'E-mail & Password' SilverStripe\Security\MemberPassword: PLURALNAME: 'Password utenti' PLURALS: @@ -313,7 +323,6 @@ it: LOGOUT: Scollegati LOSTPASSWORDHEADER: 'Password smarrita' NOTEPAGESECURED: 'La pagina è protetta. Inserisci le credenziali qui sotto per poter andare avanti.' - NOTERESETLINKINVALID: '

Il link per azzerare la password non è valido o è scaduto.

Puoi richiederne uno nuovo qui o cambiare la tua password dopo che ti sei connesso.

' NOTERESETPASSWORD: 'Inserisci il tuo indirizzo e-mail e ti verrà inviato un link per poter azzerare la tua password.' - PASSWORDSENTHEADER: 'Link per azzeramento della password inviato a ''{email}''' - PASSWORDSENTTEXT: 'Grazie! Un link di azzeramento è stato inviato a ''{email}'', fornito un account esistente per questo indirizzo e-mail.' + PASSWORDRESETSENTHEADER: 'Link di azzeramento password inviato' + PASSWORDRESETSENTTEXT: 'Grazie! Un link di azzeramento è stato inviato, supponendo un account esista a quell''indirizzo e-mail.' diff --git a/lang/ja.yml b/lang/ja.yml index b2f92eb1e..433a832e2 100644 --- a/lang/ja.yml +++ b/lang/ja.yml @@ -146,7 +146,4 @@ ja: ERRORPASSWORDPERMISSION: パスワードを変更する為に、ログインしなければなりません! LOGIN: ログイン NOTEPAGESECURED: このページはセキュリティで保護されております証明書キーを下記に入力してください。こちらからすぐに送信します - NOTERESETLINKINVALID: '

パスワードのリセットリンクは有効でないか期限切れです。

新しいパスワードを要求することができます ここ もしくはパスワードを変更することができます ログインした後 .

' NOTERESETPASSWORD: メールアドレスを入力してください、パスワードをリセットするURLを送信致します - PASSWORDSENTHEADER: 'パスワードリセットリンクは ''{email}'' に送信されました' - PASSWORDSENTTEXT: 'ありがとうございました! リセットリンクは、''{email}'' に、このアカウントが存在することを前提として送信されました。' diff --git a/lang/lt.yml b/lang/lt.yml index abdbaea25..3ca7adbff 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -167,7 +167,4 @@ lt: LOGIN: Prisijungti LOSTPASSWORDHEADER: 'Slaptažodžio atstatymas' NOTEPAGESECURED: 'Šis puslapis yra apsaugotas. Įveskite savo duomenis į žemiau esančius laukelius.' - NOTERESETLINKINVALID: '

Neteisinga arba negaliojanti slaptažodžio atstatymo nuoroda.

Galite atsisiųsti naują čia arba pasikeisti slaptažodį po to, kai prisijungsite.

' NOTERESETPASSWORD: 'Įveskite savo e. pašto adresą ir atsiųsime slaptažodžio atstatymui skirtą nuorodą' - PASSWORDSENTHEADER: 'Slaptažodžio atstatymo nuoroda nusiųsta į ''{email}''' - PASSWORDSENTTEXT: 'Atstatymo nuoroda nusiųsta į ''{email}''' diff --git a/lang/mi.yml b/lang/mi.yml index 7a2601ed5..e9fe2308e 100644 --- a/lang/mi.yml +++ b/lang/mi.yml @@ -149,7 +149,4 @@ mi: LOGIN: Takiuru LOSTPASSWORDHEADER: 'Kupuhipa Ngaro' NOTEPAGESECURED: 'Kua ngita tēnā whārangi. Tāurua ō taipitoptio tuakiri ki raro, ā, mā mātou koe e tuku kia haere tonu.' - NOTERESETLINKINVALID: '

He muhu, kua mōnehu rānei te hono tautuhi kupuhipa anō.

Ka taea te tono i te mea hōui konei ka huri rānei i tō kupuhipa ā muri i tōtakiuru.

' NOTERESETPASSWORD: 'Tāurua tō wāhitau īmēra, mā mātou e tuku tētahi hono ki a koe e taea ai te tautuhi anō i tō kupuhipa' - PASSWORDSENTHEADER: 'I tukuna he hono tautuhi kupuhipa anō ki ''{email}''' - PASSWORDSENTTEXT: 'Kia ora! Kua tukuna he hono tautuhi anō ki ''{email}'',engari rā kei te tīariari he pūkete mō taua wāhitau īmēra.' diff --git a/lang/nb.yml b/lang/nb.yml index 91dd9f758..f1dc4c74d 100644 --- a/lang/nb.yml +++ b/lang/nb.yml @@ -152,7 +152,4 @@ nb: LOGIN: 'Logg inn' LOSTPASSWORDHEADER: 'Mistet passord' NOTEPAGESECURED: 'Den siden er sikret. Skriv inn gyldig innloggingsinfo så kommer du inn.' - NOTERESETLINKINVALID: '

Lenken for å nullstille passordet er ugyldig eller utgått.

Du kan kreve en ny her eller endre passordet etter at du har logget inn.

' NOTERESETPASSWORD: 'Skriv inn epostadressen din og vi vil sende deg en lenke som nullstiller passordet.' - PASSWORDSENTHEADER: 'Lenke for nullstilling av passord ble sendt til ''{email}''' - PASSWORDSENTTEXT: 'Takk! En lenke for å lage nytt passord er sendt til ''{email}'', forutsatt at det eksisterer en konto for denne epostadressen.' diff --git a/lang/nl.yml b/lang/nl.yml index 64f191213..f6de04299 100644 --- a/lang/nl.yml +++ b/lang/nl.yml @@ -1,4 +1,26 @@ nl: + SilverStripe\Admin\LeftAndMain: + VersionUnknown: onbekend + SilverStripe\AssetAdmin\Forms\UploadField: + Dimensions: Afmetingen + EDIT: Bewerken + EDITINFO: 'Bewerk dit bestand' + REMOVE: Verwijder + SilverStripe\Control\ChangePasswordEmail_ss: + CHANGEPASSWORDFOREMAIL: 'Het wachtwoord voor het account met e-mailadres {email} is aangepast. Indien u uw wachtwoord niet heeft aangepast kunt u dat doen met onderstaande link.' + CHANGEPASSWORDTEXT1: 'U heeft het wachtwoord veranderd voor' + CHANGEPASSWORDTEXT3: 'Wachtwoord veranderen' + HELLO: Hallo + SilverStripe\Control\Email\ForgotPasswordEmail_ss: + HELLO: Hallo + TEXT1: 'Hier is uw' + TEXT2: 'link om uw wachtwoord opnieuw aan te maken' + TEXT3: voor + SilverStripe\Control\RequestProcessor: + INVALID_REQUEST: 'Fout bij verwerken' + REQUEST_ABORTED: 'Fout bij verwerken (geannuleerd)' + SilverStripe\Core\Manifest\VersionProvider: + VERSIONUNKNOWN: Onbekend SilverStripe\Forms\CheckboxField: NOANSWER: Nee YESANSWER: Ja @@ -8,6 +30,8 @@ nl: ATLEAST: 'Een wachtwoord moet tenminste {min} karakters hebben.' BETWEEN: 'Een wachtwoord moet tussen de {min} en {max} karakters hebben' CURRENT_PASSWORD_ERROR: 'Het wachtwoord dat u heeft ingevoerd is niet juist.' + CURRENT_PASSWORD_MISSING: 'Voer uw huidige wachtwoord in.' + LOGGED_IN_ERROR: 'U moet ingelogd zijn om uw wachtwoord te kunnen veranderen!' MAXIMUM: 'Een wachtwoord mag maximaal {max} karakters hebben.' SHOWONCLICKTITLE: 'Verander wachtwoord' SilverStripe\Forms\CurrencyField: @@ -16,12 +40,20 @@ nl: VALIDDATEFORMAT2: 'Vul een geldig datumformaat in ({format})' VALIDDATEMAXDATE: 'De datum moet ouder of gelijk zijn aan de maximale datum ({date})' VALIDDATEMINDATE: 'De datum moet nieuwer of gelijk zijn aan de minimale datum ({date})' + SilverStripe\Forms\DatetimeField: + VALIDDATEMAXDATETIME: 'De datum moet ouder of gelijk zijn aan de maximale datum ({datetime})' + VALIDDATETIMEFORMAT: 'Vul een geldige datum in ({format})' + VALIDDATETIMEMINDATE: 'De datum moet nieuwer of gelijk zijn aan de minimale datum ({datetime})' SilverStripe\Forms\DropdownField: CHOOSE: (Kies) + CHOOSE_MODEL: '(Selecteer {name})' SOURCE_VALIDATION: 'Selecteer een optie uit de lijst. {value} is geen geldige keuze.' SilverStripe\Forms\EmailField: VALIDATION: 'Gelieve een e-mailadres in te voeren.' + SilverStripe\Forms\FileUploadReceiver: + FIELDNOTSET: 'Bestandsinformatie niet gevonden' SilverStripe\Forms\Form: + BAD_METHOD: 'Dit formulier moet middels {method} verzonden worden' CSRF_EXPIRED_MESSAGE: 'Uw sessie is verlopen. Verzend het formulier opnieuw.' CSRF_FAILED_MESSAGE: 'Er lijkt een technisch probleem te zijn. Klik op de knop terug, vernieuw uw browser, en probeer het opnieuw.' VALIDATIONPASSWORDSDONTMATCH: 'Wachtwoorden komen niet overeen' @@ -30,7 +62,10 @@ nl: VALIDATOR: Validator VALIDCURRENCY: 'Vul een geldige munteenheid in' SilverStripe\Forms\FormField: + EXAMPLE: 'bijv. {format}' NONE: geen + SilverStripe\Forms\FormScaffolder: + TABMAIN: Hoofdgedeelte SilverStripe\Forms\GridField\GridField: Add: '{name} toevoegen' CSVEXPORT: 'Exporteer naar CSV' @@ -41,6 +76,7 @@ nl: LinkExisting: 'Koppel een bestaand item' NewRecord: 'Nieuw {type}' NoItemsFound: 'Geen items gevonden.' + OpenFilter: 'Zoeken en filteren openen' PRINTEDAT: 'Geprint op' PRINTEDBY: 'Geprint door' PlaceHolder: 'Zoek {type}' @@ -60,27 +96,72 @@ nl: DeletePermissionsFailure: 'Onvoldoende rechten om te verwijderen' Deleted: '{type} {name} verwijderd' Save: Opslaan + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Bewerken + SilverStripe\Forms\GridField\GridFieldFilterHeader: + Search: 'Zoek naar "{name}"' + SearchFormFaliure: 'Er kon geen zoekformulier worden aangemaakt' + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'U kunt uzelf niet verwijderen van deze groep, omdat u dan geen admin-rechten meer heeft.' + SilverStripe\Forms\GridField\GridFieldPaginator: + OF: van + Page: Pagina + View: Bekijk + SilverStripe\Forms\GridField\GridFieldViewButton: + VIEW: Bekijk SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Aantal FIELDLABELCURRENCY: Munteenheid + INVALID_CURRENCY: 'Valuta {currency} is niet toegestaan' + SilverStripe\Forms\MultiSelectField: + SOURCE_VALIDATION: 'Selecteer een optie uit de lijst. {value} is geen geldige keuze.' SilverStripe\Forms\NullableField: IsNullLabel: 'Is null' SilverStripe\Forms\NumericField: VALIDATION: '''{value}'' is geen getal, enkel getallen worden door dit veld geaccepteerd' SilverStripe\Forms\TimeField: VALIDATEFORMAT: 'Vul een geldig datumformaat in ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: 'Data objecten' + PLURALS: + one: 'Data object' + other: '{count} Data objecten' + SINGULARNAME: 'Data object' SilverStripe\ORM\FieldType\DBBoolean: ANY: Elke NOANSWER: Nee YESANSWER: Ja SilverStripe\ORM\FieldType\DBDate: + DAYS_SHORT_PLURALS: + one: '{count} dag' + other: '{count} dagen' + HOURS_SHORT_PLURALS: + one: '{count} uur' + other: '{count} uren' LessThanMinuteAgo: 'minder dan één minuut' + MINUTES_SHORT_PLURALS: + one: '{count} minuut' + other: '{count} minuten' + MONTHS_SHORT_PLURALS: + one: '{count} maand' + other: '{count} maanden' + SECONDS_SHORT_PLURALS: + one: '{count} seconde' + other: '{count} seconden' TIMEDIFFAGO: '{difference} geleden' TIMEDIFFIN: 'in {difference}' + YEARS_SHORT_PLURALS: + one: '{count} jaar' + other: '{count} jaren' SilverStripe\ORM\FieldType\DBEnum: ANY: Elke + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'Teveel keuzes in de lijst; een alternatief veld wordt getoond.' + SilverStripe\ORM\Hierarchy: + LIMITED_TITLE: 'Teveel onderliggende items ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: InfiniteLoopNotAllowed: 'Oneindige lus gevonden in "{type}" hiërarchie. Wijzig het hogere niveau om dit op te lossen' + LIMITED_TITLE: 'Teveel onderliggende items ({count})' SilverStripe\ORM\ValidationException: DEFAULT_ERROR: Validatiefout SilverStripe\Security\BasicAuth: @@ -91,34 +172,60 @@ nl: PASSWORDEXPIRED: '

Uw wachtwoord is verlopen. Kies een nieuw wachtwoord.

' SilverStripe\Security\CMSSecurity: INVALIDUSER: '

Ongeldige gebruiker Log hier opnieuw in om verder te gaan.

' + LOGIN_MESSAGE: 'Sessie is verlopen' + LOGIN_TITLE: '

U kunt verder met wat u aan het doen was, door opnieuw in te loggen.

' SUCCESS: Succes SUCCESSCONTENT: '

U bent ingelogd. Klik hier als u niet automatisch wordt doorgestuurd.

' + SUCCESS_TITLE: 'Inloggen is gelukt' + SilverStripe\Security\DefaultAdminService: + DefaultAdminFirstname: 'Standaard Beheerder' SilverStripe\Security\Group: AddRole: 'Voeg een rol toe aan deze groep' Code: 'Groep code' DefaultGroupTitleAdministrators: Beheerders DefaultGroupTitleContentAuthors: 'Inhoud Auteurs' Description: 'Omschrijving ' + GROUPNAME: 'Groep naam' GroupReminder: 'Als u de bovenliggende groep selecteert, neemt deze groep alle rollen over' HierarchyPermsError: 'U moet (ADMIN) rechten hebben om de bovenliggende groep "{group}" toe te kennen' Locked: 'Gesloten?' + MEMBERS: Leden + NEWGROUP: 'Nieuwe groep' NoRoles: 'Geen rollen gevonden' + PERMISSIONS: Rechten + PLURALNAME: Groepen + PLURALS: + one: 'Een groep' + other: '{count} groepen' Parent: 'Bovenliggende groep' + ROLES: Rollen + ROLESDESCRIPTION: 'Rollen zijn logische groeperingen van rechten die in het Rollen tabblad gewijzigd kunnen worden.
Rollen worden automatisch overgenomen van bovenliggende groepen.' RolesAddEditLink: 'Rollen beheren' + SINGULARNAME: Groep Sort: Sorteer-richting has_many_Permissions: Rechten many_many_Members: Leden SilverStripe\Security\LoginAttempt: + Email: 'E-mailadres ' + EmailHashed: 'E-mailadres (versleuteld)' IP: 'IP adres' + PLURALNAME: Inlogpogingen + PLURALS: + one: 'Een inlogpoging' + other: '{count} inlogpogingen' + SINGULARNAME: Inlogpogingen Status: Status SilverStripe\Security\Member: ADDGROUP: 'Groep toevoegen' BUTTONCHANGEPASSWORD: 'Wachtwoord veranderen' BUTTONLOGIN: Inloggen BUTTONLOGINOTHER: 'Als iemand anders inloggen' + BUTTONLOGOUT: Uitloggen BUTTONLOSTPASSWORD: 'Ik ben mijn wachtwoord vergeten' CONFIRMNEWPASSWORD: 'Bevestig het nieuwe wachtwoord' CONFIRMPASSWORD: 'Bevestig wachtwoord' + CURRENT_PASSWORD: 'Huidige wachtwoord' + EDIT_PASSWORD: 'Nieuw wachtwoord' EMAIL: E-mail EMPTYNEWPASSWORD: 'Het nieuwe wachtwoord mag niet leeg zijn, probeer opnieuw' ENTEREMAIL: 'Typ uw e-mailadres om een link te ontvangen waarmee u uw wachtwoord kunt resetten.' @@ -128,13 +235,21 @@ nl: ERRORWRONGCRED: 'De ingevulde gegevens lijken niet correct. Probeer het nog een keer.' FIRSTNAME: Voornaam INTERFACELANG: 'Interface taal' + KEEPMESIGNEDIN: 'Houd mij ingelogd' LOGGEDINAS: 'U bent ingelogd als {name}.' NEWPASSWORD: 'Nieuw wachtwoord' PASSWORD: Wachtwoord PASSWORDEXPIRED: 'Uw wachtwoord is verlopen. Kies een nieuw wachtwoord.' + PLURALNAME: Leden + PLURALS: + one: 'Een lid' + other: '{count} leden' + REMEMBERME: 'Onthoud mij voor volgende keer? (voor {count} dagen op dit apparaat)' + SINGULARNAME: Lid SUBJECTPASSWORDCHANGED: 'Uw wachtwoord is veranderd' SUBJECTPASSWORDRESET: 'Link om uw wachtwoord opnieuw aan te maken' SURNAME: Achternaam + VALIDATIONADMINLOSTACCESS: 'Niet mogelijk om alle admin-groepen te verwijderen van uw profiel' ValidationIdentifierFailed: 'Een bestaande gebruiker #{id} kan niet dezelfde unieke velden hebben ({name} = {value}))' WELCOMEBACK: 'Welkom terug, {firstname}' YOUROLDPASSWORD: 'Uw oude wachtwoord' @@ -143,15 +258,38 @@ nl: db_LockedOutUntil: 'Gesloten tot' db_Password: Wachtwoord db_PasswordExpiry: 'Wachtwoord vervaldatum' + SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: + AUTHENTICATORNAME: Inlogformulier + BUTTONFORGOTPASSWORD: 'Wachtwoord vergeten' + BUTTONLOGIN: 'Opnieuw inloggen' + BUTTONLOGOUT: Uitloggen + SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: + ERRORWRONGCRED: 'De ingevulde gegevens lijken niet correct. Probeer het nog een keer.' + NoPassword: 'Er is geen wachtwoord voor deze gebruiker.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'E-mail & wachtwoord' + SilverStripe\Security\MemberPassword: + PLURALNAME: Gebruikerswachtwoorden + PLURALS: + one: 'Een gebruikerswachtwoord' + other: '{count} Gebruikerswachtwoorden' + SINGULARNAME: Gebruikerswachtwoord SilverStripe\Security\PasswordValidator: LOWCHARSTRENGTH: 'Maak a.u.b. uw wachtwoord sterker door enkele van de volgende karakters te gebruiken: {chars}' PREVPASSWORD: 'U heeft dit wachtwoord in het verleden al gebruikt, kies a.u.b. een nieuw wachtwoord.' TOOSHORT: 'Het wachtwoord is te kort, het moet minimaal {minimum} karakters hebben' SilverStripe\Security\Permission: AdminGroup: Beheerder + CMS_ACCESS_CATEGORY: 'CMS toegang' CONTENT_CATEGORY: Inhoudsrechten FULLADMINRIGHTS: 'Volledige admin rechten' FULLADMINRIGHTS_HELP: 'Impliceert en overstemt alle andere toegewezen rechten.' + PERMISSIONS_CATEGORY: 'Rollen en toegangsrechten' + PLURALNAME: Rechten + PLURALS: + one: Machtiging + other: '{count} rechten' + SINGULARNAME: Machtiging UserPermissionsIntro: 'Groepen aan deze gebruiker toewijzen zullen diens permissies aanpassen. Zie de sectie Groepen voor meer informatie over machtigingen voor afzonderlijke groepen.' SilverStripe\Security\PermissionCheckboxSetField: AssignedTo: 'toegewezen aan "{title}"' @@ -161,21 +299,37 @@ nl: SilverStripe\Security\PermissionRole: OnlyAdminCanApply: 'Alleen admin kan doorvoeren' PLURALNAME: Rollen + PLURALS: + one: 'Een rol' + other: '{count} rollen' SINGULARNAME: Rol Title: Titel SilverStripe\Security\PermissionRoleCode: + PLURALNAME: 'Permissie codes' + PLURALS: + one: 'Een permissiecode' + other: '{count} permissiecodes' PermsError: 'U moet (ADMIN) rechten hebben om de code "{code}" toe te kennen' + SINGULARNAME: Permissiecode + SilverStripe\Security\RememberLoginHash: + PLURALNAME: 'Versleutelde logins' + PLURALS: + one: 'Een versleutelde login' + other: '{count} versleutelde logins' + SINGULARNAME: 'Versleutelde login' SilverStripe\Security\Security: ALREADYLOGGEDIN: 'U hebt geen toegang tot deze pagina. Als u een andere account met de nodige rechten hebt, kan u hieronder opnieuw inloggen.' BUTTONSEND: 'Nieuw wachtwoord aanmaken' CHANGEPASSWORDBELOW: 'U kunt uw wachtwoord hieronder veranderen.' CHANGEPASSWORDHEADER: 'Verander uw wachtwoord' + CONFIRMLOGOUT: 'Klik op onderstaande knop om uit te loggen.' ENTERNEWPASSWORD: 'Voer een nieuw wachtwoord in.' ERRORPASSWORDPERMISSION: 'U moet ingelogd zijn om uw wachtwoord te kunnen veranderen!' LOGIN: 'Meld aan' + LOGOUT: Uitloggen LOSTPASSWORDHEADER: 'Wachtwoord vergeten' NOTEPAGESECURED: 'Deze pagina is beveiligd. Voer uw gegevens in en u wordt automatisch doorgestuurd.' - NOTERESETLINKINVALID: '

De link om uw wachtwoord te kunnen wijzigen is niet meer geldig.

U kunt een nieuwe link aanvragen of uw wachtwoord aanpassen door in te loggen.

' + NOTERESETLINKINVALID: '

De reset link is ongeldig of komen te vervallen.

Je kan hier een nieuwe link aanvragen of het wachtwoord veranderen nadat je bent ingelogd.

' NOTERESETPASSWORD: 'Voer uw e-mailadres in en we sturen een link waarmee u een nieuw wachtwoord kunt instellen.' - PASSWORDSENTHEADER: 'Wachtwoord herstel link verzonden naar {email}' - PASSWORDSENTTEXT: 'Bedankt! Er is een link verstuurd naar {email} om uw wachtwoord opnieuw in te stellen, in de veronderstelling dat er een account bestaat voor dit e-mailadres.' + PASSWORDRESETSENTHEADER: 'link om uw wachtwoord opnieuw aan te maken' + PASSWORDRESETSENTTEXT: 'Bedankt! Er is een link verstuurd om uw wachtwoord opnieuw in te stellen (mits het mailadres reeds bekend is bij ons).' diff --git a/lang/pl.yml b/lang/pl.yml index 3774d27f3..1905acb38 100644 --- a/lang/pl.yml +++ b/lang/pl.yml @@ -84,7 +84,6 @@ pl: RelationSearch: 'Wyszukiwanie powiązań' ResetFilter: Resetuj SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Usuń Delete: Usuń DeletePermissionsFailure: 'Brak uprawnień do usuwania' EditPermissionsFailure: 'Nie masz uprawnień, aby odłączyć rekord' @@ -96,8 +95,6 @@ pl: DeletePermissionsFailure: 'Brak uprawnień do usuwania' Deleted: 'Usunięto {type} {name}' Save: Zapisz - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Edytuj SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: UnlinkSelfFailure: 'Nie możesz usunąć siebie z tej grupy, stracone zostałby prawa administratora' SilverStripe\Forms\GridField\GridFieldPaginator: @@ -352,7 +349,4 @@ pl: LOGOUT: 'Wyloguj się' LOSTPASSWORDHEADER: 'Nie pamiętam hasła' NOTEPAGESECURED: 'Ta strona jest zabezpieczona. Wpisz swoje dane a my wyślemy Ci potwierdzenie niebawem' - NOTERESETLINKINVALID: '

Link resetujący hasło wygasł lub jest nieprawidłowy.

Możesz poprosić o nowy tutaj lub zmień swoje hasło po zalogowaniu się.

' NOTERESETPASSWORD: 'Wpisz adres e-mail, na który mamy wysłać link gdzie możesz zresetować swoje hasło' - PASSWORDSENTHEADER: 'Link resetujący hasła został wysłany do ''{email}''' - PASSWORDSENTTEXT: 'Dziękujemy! Link resetujący hasło został wysłany do ''{email}'', o ile konto użytkownika dla takiego e-maila istnieje.' diff --git a/lang/ru.yml b/lang/ru.yml index 73602e013..add72be7f 100644 --- a/lang/ru.yml +++ b/lang/ru.yml @@ -339,7 +339,4 @@ ru: LOGOUT: Выйти LOSTPASSWORDHEADER: 'Восстановление пароля' NOTEPAGESECURED: 'Эта страница защищена. Пожалуйста, введите свои учетные данные для входа.' - NOTERESETLINKINVALID: '

Неверная ссылка переустановки пароля или время действия ссылки истекло.

Вы можете повторно запросить ссылку, щелкнув здесь, или поменять пароль, войдя в систему.

' NOTERESETPASSWORD: 'Введите Ваш адрес email, и Вам будет отправлена ссылка, по которой Вы сможете переустановить свой пароль' - PASSWORDSENTHEADER: 'Ссылка для переустановки пароля выслана на ''{email}''' - PASSWORDSENTTEXT: 'Ссылка переустановки пароля была выслана на адрес ''{email}'' (письмо дойдет до получателя только в том случае, если аккаунт с таким электронным адресом действительно зарегистрирован).' diff --git a/lang/sk.yml b/lang/sk.yml index 861045fc6..88f4bf260 100644 --- a/lang/sk.yml +++ b/lang/sk.yml @@ -228,7 +228,4 @@ sk: LOGIN: Prihlásiť LOSTPASSWORDHEADER: 'Zabudnuté heslo' NOTEPAGESECURED: 'Táto stránka je zabezpečená. Zadajte svoje prihlasovacie údaje a my Vám zároveň pošleme práva.' - NOTERESETLINKINVALID: '

Odkaz na resetovanie hesla nie je platný alebo je vypršala jeho platnosť.

Môžete požiadať o nový tu alebo zmeňte svoje heslo po prihlásení.

' NOTERESETPASSWORD: 'Zadajte svoju e-mailovú adresu a my Vám pošleme odkaz na resetovanie hesla' - PASSWORDSENTHEADER: 'Odkaz na resetovanie hesla bol odoslaný na ''{email}''' - PASSWORDSENTTEXT: 'Ďakujeme! Resetovací odkaz bol odoslaný na ''''{email}'''', pokiaľ účet existuje pre túto emailovú adresu.' diff --git a/lang/sl.yml b/lang/sl.yml index bccd51826..5496aff5f 100644 --- a/lang/sl.yml +++ b/lang/sl.yml @@ -135,7 +135,4 @@ sl: LOGIN: Prijava LOSTPASSWORDHEADER: 'Izgubljeno geslo' NOTEPAGESECURED: 'Stran je zaščitena. Da bi lahko nadaljevali, vpišite svoje podatke.' - NOTERESETLINKINVALID: '

Povezava za ponastavitev gesla je napačna ali pa je njena veljavnost potekla.

Tukaj lahko zaprosite za novo povezavo or pa zamenjate geslo, ko se prijavite v sistem.

' NOTERESETPASSWORD: 'Vpišite e-naslov, na katerega vam bomo poslali povezavo za ponastavitev gesla' - PASSWORDSENTHEADER: 'Povezava za ponastavitev gesla je bila poslana na e-naslov ''{email}''.' - PASSWORDSENTTEXT: 'Hvala! Povezava za ponastavitev gesla je bila poslana na e-naslov ''{email}'', ki je naveden kot e-naslov vašega računa. ' diff --git a/lang/sr.yml b/lang/sr.yml index 07f642278..622b657b3 100644 --- a/lang/sr.yml +++ b/lang/sr.yml @@ -151,7 +151,4 @@ sr: ERRORPASSWORDPERMISSION: 'Морате да будете пријављени да бисте променили своју лозинку!' LOGIN: Пријављивање NOTEPAGESECURED: 'Ова страна је обезбеђена. Унесите своје податке и ми ћемо вам послати садржај.' - NOTERESETLINKINVALID: '

Линк за ресетовање лозинке је погрешан или је истекло време за његово коришћење.

Можете да захтевате нови овде или да промените Вашу лозинку након што се пријавите.

' NOTERESETPASSWORD: 'Унесите своју адресу е-поште и ми ћемо вам послати линк помоћу којег можете да промените своју лозинку' - PASSWORDSENTHEADER: 'Линк за ресетовање лозинке послат је на адресу е-поште: ''{email}''' - PASSWORDSENTTEXT: 'Хвала Вам! Линк за ресетовање лозинке је послат не адресу е-поште ''{email}''. Порука ће стићи примаоцу само ако постоји регистрован налог са том адресом е-поште.' diff --git a/lang/sr@latin.yml b/lang/sr@latin.yml index 1b210ae51..f91aa9337 100644 --- a/lang/sr@latin.yml +++ b/lang/sr@latin.yml @@ -150,7 +150,4 @@ sr@latin: ERRORPASSWORDPERMISSION: 'Morate da budete prijavljeni da biste promenili svoju lozinku!' LOGIN: Prijavljivanje NOTEPAGESECURED: 'Ova strana je obezbeđena. Unesite svoje podatke i mi ćemo vam poslati sadržaj.' - NOTERESETLINKINVALID: '

Link za resetovanje lozinke je pogrešan ili je isteklo vreme za njegovo korišćenje.

Možete da zahtevate novi ovde ili da promenite Vašu lozinku nakon što se prijavite.

' NOTERESETPASSWORD: 'Unesite svoju adresu e-pošte i mi ćemo vam poslati link pomoću kojeg možete da promenite svoju lozinku' - PASSWORDSENTHEADER: 'Link za resetovanje lozinke poslat je na adresu e-pošte: ''{email}''' - PASSWORDSENTTEXT: 'Hvala Vam! Link za resetovanje lozinke je poslat ne adresu e-pošte ''{email}''. Poruka će stići primaocu samo ako postoji registrovan nalog sa tom adresom e-pošte.' diff --git a/lang/sr_RS.yml b/lang/sr_RS.yml index fc79812da..298049430 100644 --- a/lang/sr_RS.yml +++ b/lang/sr_RS.yml @@ -150,7 +150,4 @@ sr_RS: ERRORPASSWORDPERMISSION: 'Морате да будете пријављени да бисте променили своју лозинку!' LOGIN: Пријављивање NOTEPAGESECURED: 'Ова страна је обезбеђена. Унесите своје податке и ми ћемо вам послати садржај.' - NOTERESETLINKINVALID: '

Линк за ресетовање лозинке је погрешан или је истекло време за његово коришћење.

Можете да захтевате нови овде или да промените Вашу лозинку након што се пријавите.

' NOTERESETPASSWORD: 'Унесите своју адресу е-поште и ми ћемо вам послати линк помоћу којег можете да промените своју лозинку' - PASSWORDSENTHEADER: 'Линк за ресетовање лозинке послат је на адресу е-поште: ''{email}''' - PASSWORDSENTTEXT: 'Хвала Вам! Линк за ресетовање лозинке је послат не адресу е-поште ''{email}''. Порука ће стићи примаоцу само ако постоји регистрован налог са том адресом е-поште.' diff --git a/lang/sr_RS@latin.yml b/lang/sr_RS@latin.yml index f39b36058..453ffa17d 100644 --- a/lang/sr_RS@latin.yml +++ b/lang/sr_RS@latin.yml @@ -151,7 +151,4 @@ sr_RS@latin: ERRORPASSWORDPERMISSION: 'Morate da budete prijavljeni da biste promenili svoju lozinku!' LOGIN: Prijavljivanje NOTEPAGESECURED: 'Ova strana je obezbeđena. Unesite svoje podatke i mi ćemo vam poslati sadržaj.' - NOTERESETLINKINVALID: '

Link za resetovanje lozinke je pogrešan ili je isteklo vreme za njegovo korišćenje.

Možete da zahtevate novi ovde ili da promenite Vašu lozinku nakon što se prijavite.

' NOTERESETPASSWORD: 'Unesite svoju adresu e-pošte i mi ćemo vam poslati link pomoću kojeg možete da promenite svoju lozinku' - PASSWORDSENTHEADER: 'Link za resetovanje lozinke poslat je na adresu e-pošte: ''{email}''' - PASSWORDSENTTEXT: 'Hvala Vam! Link za resetovanje lozinke je poslat ne adresu e-pošte ''{email}''. Poruka će stići primaocu samo ako postoji registrovan nalog sa tom adresom e-pošte.' diff --git a/lang/sv.yml b/lang/sv.yml index f35c2ee99..f2a18d659 100644 --- a/lang/sv.yml +++ b/lang/sv.yml @@ -93,7 +93,12 @@ sv: DeletePermissionsFailure: 'Rättighet för att radera saknas' Deleted: 'Raderade {type} {name}' Save: Spara + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Ändra + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Du kan inte radera dig själv från den här gruppen, då du då kommer att förlora dina admin-rättigheter' SilverStripe\Forms\GridField\GridFieldPaginator: + OF: av Page: Sida View: Visa SilverStripe\Forms\MoneyField: @@ -108,6 +113,12 @@ sv: VALIDATION: '''{value}'' är inget nummer, bara siffror (utan mellanslag) kan accepteras för det här fältet' SilverStripe\Forms\TimeField: VALIDATEFORMAT: 'Var god att ange tid i ett giltigt format ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: Dataobjekt + PLURALS: + one: 'Ett dataobjekt' + other: '{count} Dataobjekt' + SINGULARNAME: Dataobjekt SilverStripe\ORM\FieldType\DBBoolean: ANY: 'Vilken som helst' NOANSWER: Nej @@ -136,6 +147,8 @@ sv: other: '{count} år' SilverStripe\ORM\FieldType\DBEnum: ANY: 'Vilken som helst' + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'För många relaterade objekt; använder fallback-fält' SilverStripe\ORM\Hierarchy: LIMITED_TITLE: 'För många barn ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: @@ -221,6 +234,7 @@ sv: PLURALS: one: 'En medlem' other: '{count} medlemmar' + REMEMBERME: 'Kom ihåg mig nästa gång? (i {count} dagar på denna enhet)' SINGULARNAME: Medlem SUBJECTPASSWORDCHANGED: 'Ditt lösenord har ändrats' SUBJECTPASSWORDRESET: 'Din återställningslänk' @@ -288,7 +302,6 @@ sv: LOGOUT: 'Logga ut' LOSTPASSWORDHEADER: 'Bortglömt lösenord' NOTEPAGESECURED: 'Den här sidan är låst. Fyll i dina uppgifter nedan så skickar vi dig vidare.' - NOTERESETLINKINVALID: '

Återställningslänk för lösenord är felaktig eller för gammal.

Du kan begära en ny här eller ändra ditt lösenord när du loggat in.

' NOTERESETPASSWORD: 'Ange din e-postadress så skickar vi en länk med vilken du kan återställa ditt lösenord' - PASSWORDSENTHEADER: 'Återställningslänk för lösenord har skickats till ''{email}''' - PASSWORDSENTTEXT: 'Tack en återställningslänk har skickats till ''{email}'', förutsatt att ett konto med den addressen finns.' + PASSWORDRESETSENTHEADER: 'Återställningslänk för lösenord skickad' + PASSWORDRESETSENTTEXT: 'Tack. En återställningslänk har skickats, förutsatt att ett konto med denna adress existerar.' diff --git a/lang/zh.yml b/lang/zh.yml index 26c8e2893..748ee671c 100644 --- a/lang/zh.yml +++ b/lang/zh.yml @@ -166,7 +166,4 @@ zh: LOGIN: 登录 LOSTPASSWORDHEADER: 忘记密码 NOTEPAGESECURED: 该页面受安全保护。请在下面输入您的证书,然后我们会立即将您引导至该页面。 - NOTERESETLINKINVALID: '

密码重设链接无效或已过期。

您可以在这里 要求一个新的或在登录后更改您的密码。

' NOTERESETPASSWORD: 请输入您的电子邮件地址,然后我们会将一个链接发送给您,您可以用它来重设您的密码 - PASSWORDSENTHEADER: '密码重设链接已发送至''{email}''' - PASSWORDSENTTEXT: '谢谢!复位链接已发送到 ''{email}'',假定此电子邮件地址存在一个帐户。' From a65d313fd79dd5078b26d496f889e31da9054df2 Mon Sep 17 00:00:00 2001 From: Aaron Carlino Date: Wed, 7 Nov 2018 19:12:38 +1300 Subject: [PATCH 12/17] Added 4.2.2 changelog --- docs/en/04_Changelogs/4.2.2.md | 61 ++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 docs/en/04_Changelogs/4.2.2.md diff --git a/docs/en/04_Changelogs/4.2.2.md b/docs/en/04_Changelogs/4.2.2.md new file mode 100644 index 000000000..f0df5cec5 --- /dev/null +++ b/docs/en/04_Changelogs/4.2.2.md @@ -0,0 +1,61 @@ +# 4.2.2 + + + +## Change Log + +### Security + + * 2018-08-21 [0610f76da](https://github.com/silverstripe/silverstripe-framework/commit/0610f76da02ac53a1b51cdfe9eac34e943a66991) Add confirmation token to dev/build (Loz Calver) - See [ss-2018-019](https://www.silverstripe.org/download/security-releases/ss-2018-019) + * 2018-08-12 [909ab03](https://github.com/silverstripe/silverstripe-admin/commit/909ab03fc4e742a05a06c33c5233691fd7466836) Add CSRF to Apollo (Aaron Carlino) - See [ss-2018-007](https://www.silverstripe.org/download/security-releases/ss-2018-007) + * 2018-07-29 [214e28127](https://github.com/silverstripe/silverstripe-framework/commit/214e28127f5425b61c15b69f884afdbad31133c2) Ignore arguments in mysqli::real_connect backtrace calls (Robbie Averill) - See [ss-2018-018](https://www.silverstripe.org/download/security-releases/ss-2018-018) + +### Features and Enhancements + + * 2018-08-24 [2b335b4](https://github.com/silverstripe/silverstripe-graphql/commit/2b335b4239946f9a6fb1d525452cf1fe6d22a9ce) Proof of concept of cached graphql queries (#166) (Damian Mooyman) + * 2018-07-01 [73d3da2](https://github.com/silverstripe/silverstripe-admin/commit/73d3da2bc8566cb1cb5da0124b7deb513728b5ab) Pattern library now has FormAction examples (Robbie Averill) + +### Bugfixes + + * 2018-10-24 [e72fc9e3d](https://github.com/silverstripe/silverstripe-framework/commit/e72fc9e3d0f35a1d43f55f83f9919f67d72fb7cb) DataObject singleton creation (#8516) (Sam Minnée) + * 2018-10-19 [7c65916](https://github.com/silverstripe/silverstripe-asset-admin/commit/7c659167f2eda63d882a097f2f413b9f3cb79e31) Use fixtured file title in test assertion (Robbie Averill) + * 2018-10-17 [d71ee0c](https://github.com/silverstripe/silverstripe-admin/commit/d71ee0ce9898e73c9a7d913356fc6bfe6c2b42fc) Fixes #674 TinyMCE width - this should match form field widths at lower width resolutions but expand up to the max width on wider resolutions (bergice) + * 2018-10-16 [a6a174399](https://github.com/silverstripe/silverstripe-framework/commit/a6a17439976710b2311558d363b5467fa429dcca) Fix `ENTER` not triggering form save button as `GridField`s used `submit` type buttons (bergice) + * 2018-10-14 [c0c446a](https://github.com/silverstripe/silverstripe-versioned/commit/c0c446ad8f29dd66398feb38f5d92fa4f60a4a8b) Fix relations between staged/unstaged objects (Harsh Chokshi) + * 2018-10-09 [f710c5c](https://github.com/silverstripe/silverstripe-admin/commit/f710c5cdcd2cf95fdaa738f55c0f2529fcbe826d) Only hide overflow from inactive chosen fields (Robbie Averill) + * 2018-10-01 [5422e28](https://github.com/silverstripe/silverstripe-asset-admin/commit/5422e28635cec8f285eb422fa85f57f4418c09b8) Folder sort incorrect (Luke Edwards) + * 2018-09-28 [231d6d9a9](https://github.com/silverstripe/silverstripe-framework/commit/231d6d9a9f388e10cf77149aec22e947db648644) New members now receive the configured default locale, not the current locale (Robbie Averill) + * 2018-09-21 [1d5ecd342](https://github.com/silverstripe/silverstripe-framework/commit/1d5ecd342e417b4707a3bbc34e97949bffd14afb) Prevent error on valid response status codes (Damian Mooyman) + * 2018-09-18 [bbe7c66](https://github.com/silverstripe/silverstripe-asset-admin/commit/bbe7c660cf40d4c942eaf6e76755eeaf46c63471) Add `AssetAdmin::getMinimalistObjectFromData()` to build file metadata for UploadField (#829) (Maxime Rainville) + * 2018-09-18 [db63f55fb](https://github.com/silverstripe/silverstripe-framework/commit/db63f55fbb8e635e4e7215b7b7eff4e1f1cb7b22) Changes being detected on TreeMulti as values not sorted (Luke Edwards) + * 2018-09-13 [5c102dec](https://github.com/silverstripe/silverstripe-cms/commit/5c102decbde43395e14aeff83a20c4c6f1d048ae) Improve performance of CMSMain::getArchiveWarningMessage (#2231) (Maxime Rainville) + * 2018-09-10 [8ae0ef0](https://github.com/silverstripe/silverstripe-versioned/commit/8ae0ef0002a229d233f7395cfed15c979c3f1698) Do not update LeftAndMain link with Stage param (#173) (Maxime Rainville) + * 2018-09-03 [1c4311d](https://github.com/silverstripe/silverstripe-asset-admin/commit/1c4311d4e6548600272daa0ce83afa12cf7e99c3) fix description for docs.silverstripe.org (wernerkrauss) + * 2018-09-03 [b922c0d73](https://github.com/silverstripe/silverstripe-framework/commit/b922c0d7327b5d0222dd280afcb64f83a09ea859) Check scheme is truthy before setting it to the request (Robbie Averill) + * 2018-08-31 [68c2c976d](https://github.com/silverstripe/silverstripe-framework/commit/68c2c976d4813607a420ac4cda7b01f0a7aee8c7) Fix alignment test step definition (#8354) (Luke Edwards) + * 2018-08-30 [234b795f8](https://github.com/silverstripe/silverstripe-framework/commit/234b795f89657c6b25da6101a9fc878e3297c301) Use classes for TinyMCE alignment buttons (Luke Edwards) + * 2018-08-28 [d651d0fbf](https://github.com/silverstripe/silverstripe-framework/commit/d651d0fbfcababeaf317b27cb00b4f33b9d99eab) Use base class (not remapping target class) when looking up whether object is versioned (Robbie Averill) + * 2018-08-27 [4da556923](https://github.com/silverstripe/silverstripe-framework/commit/4da5569232505ee574e0b5106ff2116611393aa4) ensure createFromVariables takes correct params on CLIRequestBuilder (Scott Hutchinson) + * 2018-08-27 [f3230c78](https://github.com/silverstripe/silverstripe-reports/commit/f3230c78d4e3731a10a5f4c508bc68c6a8534866) Use requestVar() to include post vars as well as get vars (Robbie Averill) + * 2018-08-23 [f37dd74](https://github.com/silverstripe/silverstripe-admin/commit/f37dd74be7afae5e40e85ce2a90a4d92bf7e80bb) Site tree items do not disappear on save with source file comments enabled (Robbie Averill) + * 2018-08-20 [dbab69669](https://github.com/silverstripe/silverstripe-framework/commit/dbab6966908f0a293ee6d469cec6b4650dc5a0f1) Message when changing password with invalid token now contains correct links to login (Robbie Averill) + * 2018-08-20 [9da7f99](https://github.com/silverstripe/silverstripe-versioned/commit/9da7f991f33ac16070b2e47b764b216a87f96622) Draft content requiring login message now correctly renders HTML link (Robbie Averill) + * 2018-08-17 [c361b09](https://github.com/silverstripe/silverstripe-admin/commit/c361b091b1640c25f1d23914489212fce1e29377) overflow of chosen dropdowns when inactive (Scott Hutchinson) + * 2018-08-16 [66cd3af](https://github.com/silverstripe/silverstripe-admin/commit/66cd3af09fcf68bf177a46ac57434442642d1b7c) Filtering or paginating a gridfield causing a change event (Luke Edwards) + * 2018-08-15 [0db594b2d](https://github.com/silverstripe/silverstripe-framework/commit/0db594b2d39c93dd2e911414bee5520c84048906) Remove double escaping of HTML values in print views (Robbie Averill) + * 2018-08-15 [0c713b5](https://github.com/silverstripe/silverstripe-assets/commit/0c713b5b1eb6a08ac00dcadb187b8b3ef7115fc4) Fix routing for files with dots in filename (Damian Mooyman) + * 2018-08-14 [873873dc3](https://github.com/silverstripe/silverstripe-framework/commit/873873dc303ce2041aa23e365464133a359e1561) Pass request to dummy controller before calling init (Robbie Averill) + * 2018-08-14 [27ac001d5](https://github.com/silverstripe/silverstripe-framework/commit/27ac001d5b27cce4f80ce4b3335c14708b116830) email rendering should not include requirements (Thomas Portelange) + * 2018-08-14 [8ec551e5](https://github.com/silverstripe/silverstripe-cms/commit/8ec551e57b04d00d6897d06c2779557f0ec8109d) Broken "show as list" (#2232) (Maxime Rainville) + * 2018-08-12 [9f5b0086c](https://github.com/silverstripe/silverstripe-framework/commit/9f5b0086cb1a0259c5c87ea205390c5e69dcae90) Paginating a gridfield causing a change event (Luke Edwards) + * 2018-08-10 [d4995f52](https://github.com/silverstripe/silverstripe-cms/commit/d4995f5204f020f75fbddb3e49b944a54be5c6c2) Separating ModelAsController catch-all route to apply after all other configuration (Guy Marriott) + * 2018-08-08 [e14ab99](https://github.com/silverstripe/silverstripe-graphql/commit/e14ab991f5c99cee6b1bdfa18ab07a1e4b40961e) Don't rely on return value of GraphQL scaffolding providers (#171) (Guy Marriott) + * 2018-08-06 [df7396e8](https://github.com/silverstripe/silverstripe-cms/commit/df7396e8845eea7a75e73237de9ee7e4cb6568f6) CMS routes are now run after #coreroutes without re-including itself (Robbie Averill) + * 2018-07-27 [85b4b48fb](https://github.com/silverstripe/silverstripe-framework/commit/85b4b48fb5489cdba4b18cbf510d883986dd61c1) Restore default delete action on GridFieldConfig_RecordEditor (Maxime Rainville) + * 2018-07-27 [0d90cdb05](https://github.com/silverstripe/silverstripe-framework/commit/0d90cdb05d058763e5e52720ab653c5cc391dc3b) Altering ID of authenticator tabs to resolve ID conflict (Guy Marriott) + * 2018-07-26 [fea9ef7](https://github.com/silverstripe/silverstripe-admin/commit/fea9ef7d2a53904086f9fad6eedba7bb307c8578) #579 BUG Ambiguous column RecordID when doing batch actions (Ed Linklater) + * 2018-07-23 [a0487e5](https://github.com/silverstripe/silverstripe-admin/commit/a0487e59fc04af0d15e66d4c2874051288b4e63e) Treat readonly as disabled and fix handling for ui-constructive class (Robbie Averill) + * 2018-07-16 [e1296d48](https://github.com/silverstripe/silverstripe-reports/commit/e1296d4813ac1b677aa7a612ba0ad3b2ba62ccae) Filter var can be returned correctly from get variables as a fallback (Robbie Averill) + * 2018-06-27 [8ccebf8](https://github.com/silverstripe/silverstripe-admin/commit/8ccebf813e95980363a92ec37332d2241327441f) Stop sslink from hijacking anchor plugin (Will Rossiter) + * 2018-05-18 [953153500](https://github.com/silverstripe/silverstripe-framework/commit/953153500d490f5b5abf7283c34242c3b22a855a) Polymorphic relationship class columns have obsolete class names remapped (Robbie Averill) + * 2018-05-08 [97a8f56](https://github.com/silverstripe/silverstripe-admin/commit/97a8f56c43ddb3c77a5bbc452755d44afb9a9472) Add missing focus styles for preview options (fixes silverstripe/silverstripe-framework #2101) (Loz Calver) From 26d404ca4ce1ca3f09d3334d4091995525b6b7f4 Mon Sep 17 00:00:00 2001 From: Vagrant Default User Date: Wed, 7 Nov 2018 21:37:35 +1300 Subject: [PATCH 13/17] Update translations --- lang/ar.yml | 3 - lang/bg.yml | 3 - lang/cs.yml | 3 - lang/da.yml | 325 ++++++++++++++++++++++++++++++++++++++++++- lang/de.yml | 3 - lang/eo.yml | 9 +- lang/es.yml | 3 - lang/et_EE.yml | 3 - lang/fa_IR.yml | 1 - lang/fi.yml | 11 +- lang/fr.yml | 3 - lang/id.yml | 3 - lang/id_ID.yml | 3 - lang/it.yml | 15 +- lang/ja.yml | 3 - lang/lt.yml | 3 - lang/mi.yml | 3 - lang/nb.yml | 3 - lang/nl.yml | 154 +++++++++++++++++++- lang/pl.yml | 202 ++++++++++++++++++++++++++- lang/ru.yml | 3 - lang/sk.yml | 3 - lang/sl.yml | 3 - lang/sr.yml | 3 - lang/sr@latin.yml | 3 - lang/sr_RS.yml | 3 - lang/sr_RS@latin.yml | 3 - lang/sv.yml | 19 ++- lang/zh.yml | 3 - 29 files changed, 716 insertions(+), 83 deletions(-) diff --git a/lang/ar.yml b/lang/ar.yml index 19381589f..518bf1344 100644 --- a/lang/ar.yml +++ b/lang/ar.yml @@ -150,7 +150,4 @@ ar: LOGIN: دخول LOSTPASSWORDHEADER: 'كلمة مرور مفقودة' NOTEPAGESECURED: 'هذه الصفحة محمية بكلمة مرور ، أدخل بيانات دخولك بالأسفل ليتم السماح لك بالوصول للصفحة' - NOTERESETLINKINVALID: "

رابط إعادة تعيين كلمة المرور غير صحيح أو نفذت صلاحيته.

\n

\nيمكنك طلب رابط جديد <\"{a href=\"{link1\"> هنا \n أو تغيير كلمة المرور الخاصة بك بعد <\"{a href=\"{link2\"> تسجيل دخولك.\n

" NOTERESETPASSWORD: 'أدخل بريدك الإلكتروني و سيتم إرسال رابط إعادة تهيئة كلمة المرور ' - PASSWORDSENTHEADER: 'رابط استعادة كلمة المرور تم إرساله إلى ''{بريدك}''' - PASSWORDSENTTEXT: 'شكرا لك! تم إرسال رابط إعادة تعيين إلى ''{بريدك}''، بشرط وجود حساب قائم بالنسبة لعنوان هذا البريد الإلكتروني .' diff --git a/lang/bg.yml b/lang/bg.yml index 3e1eba6a0..241841f1e 100644 --- a/lang/bg.yml +++ b/lang/bg.yml @@ -313,7 +313,4 @@ bg: LOGOUT: Изход LOSTPASSWORDHEADER: 'Забравена парола' NOTEPAGESECURED: 'Тази страница е защитена. Въведете вашите данни по-долу, за да продължите.' - NOTERESETLINKINVALID: '

Връзката за нулиране на парола не е вярна или е просрочена.

Можете да заявите нова тук или да промените паролата си след като влезете.

' NOTERESETPASSWORD: 'Въведете вашият email адрес и ще ви изпратим линк, с който ще можете да смените паролата си' - PASSWORDSENTHEADER: 'Връзка за нулиране на парола беше изпратена на ''{email}''' - PASSWORDSENTTEXT: 'Благодарим ви! Връзка за нулиране на паролата беше изпратен на ''{email}'', ако съществува акаунт с този имейл адрес.' diff --git a/lang/cs.yml b/lang/cs.yml index 4a3cae3ab..759f0268e 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -194,7 +194,4 @@ cs: LOGIN: Přihlásit LOSTPASSWORDHEADER: 'Zapomenuté heslo' NOTEPAGESECURED: 'Tato stránka je zabezpečená. Vložte své přihlašovací údaje a my Vám zároveň pošleme práva.' - NOTERESETLINKINVALID: '

Odkaz na resetování hesla není platný nebo je prošlý.

Můžete požádat o nový zde nebo změňte své heslo až se přihlásíte.

' NOTERESETPASSWORD: 'Zadejte svou e-mailovou adresu a bude vám zaslán nulovací odkaz pro Vaše heslo' - PASSWORDSENTHEADER: 'Odkaz na resetování hesla byl odeslán na ''{email}''' - PASSWORDSENTTEXT: 'Děkujeme! Resetovací odkaz byl odeslán na ''{email}'', pokud účet existuje pro tuto emailovou adresu.' diff --git a/lang/da.yml b/lang/da.yml index 8dc512b23..3fe62969a 100644 --- a/lang/da.yml +++ b/lang/da.yml @@ -1,5 +1,328 @@ da: + SilverStripe\Admin\LeftAndMain: + VersionUnknown: ukendt + SilverStripe\AssetAdmin\Forms\UploadField: + Dimensions: Dimensioner + EDIT: Rediger + EDITINFO: 'Rediger denne fil' + REMOVE: Fjern + SilverStripe\Control\ChangePasswordEmail_ss: + CHANGEPASSWORDFOREMAIL: 'Koden for kontoen med email addressen {email} er ændret. Hvis du ikke har skiftet din kode, så skift venligst din kode ved at klikke på linket herunder' + CHANGEPASSWORDTEXT1: 'Du skiftede dit kodeord for' + CHANGEPASSWORDTEXT3: 'Skift kodeord' + HELLO: Hej + SilverStripe\Control\Email\ForgotPasswordEmail_ss: + HELLO: Hej + TEXT1: 'Her er din' + TEXT2: 'link til at nulstille dit kodeord' + TEXT3: for + SilverStripe\Control\RequestProcessor: + INVALID_REQUEST: 'Ugyldig forespørgsel' + REQUEST_ABORTED: 'Forespørgsel annulleret' + SilverStripe\Core\Manifest\VersionProvider: + VERSIONUNKNOWN: Ukendt + SilverStripe\Forms\CheckboxField: + NOANSWER: Nej + YESANSWER: Ja + SilverStripe\Forms\CheckboxSetField_ss: + NOOPTIONSAVAILABLE: 'Ingen tilgængelige muligheder' + SilverStripe\Forms\ConfirmedPasswordField: + ATLEAST: 'Kodeord skal være mindst {min} tegn lang.' + BETWEEN: 'Kodeord skal være {min} til {max} karakterer lang.' + CURRENT_PASSWORD_ERROR: 'Det nuværende kodeord du har indtastet er ikke korrekt.' + CURRENT_PASSWORD_MISSING: 'Du skal indtaste dit nuværende kodeord.' + LOGGED_IN_ERROR: 'Du skal være logget ind for at skifte dit kodeord.' + MAXIMUM: 'Kodeord må maks være {max} tegn lang' + SHOWONCLICKTITLE: 'Skift kodeord' + SilverStripe\Forms\CurrencyField: + CURRENCYSYMBOL: DKK + SilverStripe\Forms\DateField: + VALIDDATEFORMAT2: 'Indtats venligst et gyldigt datoformat ({format})' + VALIDDATEMAXDATE: 'Din dato skal være ældre end eller matche den maksimalt tilladte dato ({date})' + VALIDDATEMINDATE: 'Din dato skal være yngre end eller matche den minimum tilladte dato ({date})' + SilverStripe\Forms\DatetimeField: + VALIDDATEMAXDATETIME: 'Din dato skal være ældre end eller matche den maksimalt tilladte dato ({datetime})' + VALIDDATETIMEFORMAT: 'Indtats venligst et gyldigt dato- og tidsformat ({format})' + VALIDDATETIMEMINDATE: 'Din dato skal være yngre end eller matche den minimum tilladte dato og tid ({datetime})' + SilverStripe\Forms\DropdownField: + CHOOSE: (Vælg) + CHOOSE_MODEL: '(Vælg {name})' + SOURCE_VALIDATION: 'Venligst vælg en eksisterende værdi fra listen. {value} er ikke en tilladt mulighed' + SilverStripe\Forms\EmailField: + VALIDATION: 'Indtast venligst en emailadresse' + SilverStripe\Forms\FileUploadReceiver: + FIELDNOTSET: 'Fil information ikke fundet' + SilverStripe\Forms\Form: + BAD_METHOD: 'Denne form kræver en {method} indsendelse' + CSRF_EXPIRED_MESSAGE: 'Din session er udløbet. Venligst gensend formularen.' + CSRF_FAILED_MESSAGE: 'Det ser ud til der har været et teknisk problem. Klik venligst på tilbageknappen, tryk opdater i din browser og prøv igen.' + VALIDATIONPASSWORDSDONTMATCH: 'Kodeordene er ikke identiske' + VALIDATIONPASSWORDSNOTEMPTY: 'Kodeord kan ikke være tomme' + VALIDATIONSTRONGPASSWORD: 'Kodeord skal mindst have et tal og et alfanumerisk tegn' + VALIDATOR: Validering + VALIDCURRENCY: 'Indtast venligst en gyldig valuta' + SilverStripe\Forms\FormField: + EXAMPLE: 'f.eks. {format}' + NONE: ingen + SilverStripe\Forms\FormScaffolder: + TABMAIN: Primær SilverStripe\Forms\GridField\GridField: - Filter: Filter + Add: 'Tilføj {name}' + CSVEXPORT: 'Eksporter til CSV' + CSVIMPORT: 'Importer CSV' + Filter: Filtrer + FilterBy: 'Filtrer på' + Find: Find + LinkExisting: 'Link eksisterende' + NewRecord: 'Ny {type}' + NoItemsFound: 'Ingen elementer fundet' + PRINTEDAT: 'Printet d.' + PRINTEDBY: 'Printet af' + PlaceHolder: 'Find {type}' + PlaceHolderWithLabels: 'Find {type} på {name}' + Print: Print + RelationSearch: Relationssøgning + ResetFilter: Nulstil + SilverStripe\Forms\GridField\GridFieldDeleteAction: + Delete: Slet + DeletePermissionsFailure: 'Ingen slette rettigheder' + EditPermissionsFailure: 'Ingen rettighed til at fjerne emnet' + UnlinkRelation: Fjern + SilverStripe\Forms\GridField\GridFieldDetailForm: + CancelBtn: Annuller + Create: Opret + Delete: Slet + DeletePermissionsFailure: 'Ingen slette rettigheder' + Deleted: 'Slet {type} {name}' + Save: Gem + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Rediger + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Kan ikke fjerne dig selv fra denne gruppe, du vil miste administrator rettigheder' + SilverStripe\Forms\GridField\GridFieldPaginator: + OF: af + Page: Side + View: Vis + SilverStripe\Forms\MoneyField: + FIELDLABELAMOUNT: Beløb + FIELDLABELCURRENCY: Valuta + INVALID_CURRENCY: 'Valuta {currency} er ikke i listen over tilladte valutaer' + SilverStripe\Forms\MultiSelectField: + SOURCE_VALIDATION: 'Vælg venligst eksisterende værdier fra listen. Ugyldig mulighed(er) {value} valgt' + SilverStripe\Forms\NullableField: + IsNullLabel: 'Er Null' + SilverStripe\Forms\NumericField: + VALIDATION: '''{value}'' er ikke et tal, kun tal accepteres i dette felt' + SilverStripe\Forms\TimeField: + VALIDATEFORMAT: 'Indtats venligst et gyldigt tidsformat ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: Dataobjekter + PLURALS: + one: 'Et dataobjekt' + other: '{count} dataobjekter' + SINGULARNAME: Dataobjekt + SilverStripe\ORM\FieldType\DBBoolean: + ANY: Enhver + NOANSWER: Nej + YESANSWER: Ja + SilverStripe\ORM\FieldType\DBDate: + DAYS_SHORT_PLURALS: + one: '{count} dag' + other: '{count} dage' + HOURS_SHORT_PLURALS: + one: '{count} time' + other: '{count} timer' + LessThanMinuteAgo: 'mindre end et minut' + MINUTES_SHORT_PLURALS: + one: '{count} minut' + other: '{count} minutter' + MONTHS_SHORT_PLURALS: + one: '{count} måned' + other: '{count} måneder' + SECONDS_SHORT_PLURALS: + one: '{count} sekund' + other: '{count} sekunder' + TIMEDIFFAGO: '{difference} siden' + TIMEDIFFIN: 'i {difference}' + YEARS_SHORT_PLURALS: + one: '{count} år' + other: '{count} år' + SilverStripe\ORM\FieldType\DBEnum: + ANY: Enhver + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'For mange relaterede objekter; fallback felt i brug' + SilverStripe\ORM\Hierarchy: + LIMITED_TITLE: 'For mange underelementer ({count})' + SilverStripe\ORM\Hierarchy\Hierarchy: + InfiniteLoopNotAllowed: 'Uendeligt løkke fundet i "{type}" hierarkiet. Ændre venligst det overliggende element for at løse dette' + LIMITED_TITLE: 'For mange underelementer ({count})' + SilverStripe\ORM\ValidationException: + DEFAULT_ERROR: Valideringsfejl + SilverStripe\Security\BasicAuth: + ENTERINFO: 'Indtast venligst et brugernavn og kodeord.' + ERRORNOTADMIN: 'Den bruger er ikke en administrator.' + ERRORNOTREC: 'Brugernavn / kodeord kunne ikke genkendes' + SilverStripe\Security\CMSMemberLoginForm: + PASSWORDEXPIRED: '

Dit kodeord er udløbet. Vælg venligst et nyt.

' + SilverStripe\Security\CMSSecurity: + INVALIDUSER: '

Ugyldig bruger. Log venligst ind igen her for at fortsætte.

' + LOGIN_MESSAGE: '

Din session er løbet ud pga. inaktivitet

' + LOGIN_TITLE: 'Log ind igen, for at fortsætte hvor du slap.' + SUCCESS: Succes + SUCCESSCONTENT: '

Logget ind. Hvis du ikke automatisk viderestilles så klik her

' + SUCCESS_TITLE: 'Logget ind med sucess' + SilverStripe\Security\DefaultAdminService: + DefaultAdminFirstname: 'Standard admin' + SilverStripe\Security\Group: + AddRole: 'Tilføj en rolle for denne gruppe' + Code: 'Gruppe kode' + DefaultGroupTitleAdministrators: Administratorer + DefaultGroupTitleContentAuthors: Indholdsforfattere + Description: Beskrivelse + GROUPNAME: Gruppenavn + GroupReminder: 'Hvis du vælger en overliggende gruppe, får denne gruppe alle dens roller' + HierarchyPermsError: 'Kan ikke tildele overliggende gruppe "{group}" med fortrinsrettigheder (kræver ADMIN adgang)' + Locked: 'Låst?' + MEMBERS: Brugere + NEWGROUP: 'Ny gruppe' + NoRoles: 'Ingen roller fundet' + PERMISSIONS: Rettigheder + PLURALNAME: Grupper + PLURALS: + one: 'En gruppe' + other: '{count} grupper' + Parent: 'Overliggende gruppe' + ROLES: Roller + ROLESDESCRIPTION: 'Roller er et prædefineret sæt af rettigheder, som kan tildeles grupper.
De bliver nedarvet fra en overliggende grupper hvis krævet.' + RolesAddEditLink: 'Administrer roller' + SINGULARNAME: Gruppe + Sort: Sortering + has_many_Permissions: Rettigheder + many_many_Members: Brugere + SilverStripe\Security\LoginAttempt: + Email: 'Email adresse' + EmailHashed: 'Email adresse (hashed)' + IP: 'IP addresse' + PLURALNAME: Loginforsøg + PLURALS: + one: 'Et loginforsøg' + other: '{count} loginforsøg' + SINGULARNAME: 'Login forsøg' + Status: Status + SilverStripe\Security\Member: + ADDGROUP: 'Tilføj gruppe' + BUTTONCHANGEPASSWORD: 'Skift kodeord' + BUTTONLOGIN: 'Log ind' + BUTTONLOGINOTHER: 'Log ind med en anden bruger' + BUTTONLOGOUT: 'Log ud' + BUTTONLOSTPASSWORD: 'Jeg har glemt mit kodeord' + CONFIRMNEWPASSWORD: 'Bekræft nyt kodeord' + CONFIRMPASSWORD: 'Bekræft kodeord' + CURRENT_PASSWORD: 'Nuværende kodeord' + EDIT_PASSWORD: 'Nyt kodeord' + EMAIL: Email + EMPTYNEWPASSWORD: 'Det nye kodeord kan ikke være tom, prøv venligst igen' + ENTEREMAIL: 'Indtast venligst en email adresse for at få et nulstillingslink.' + ERRORLOCKEDOUT2: 'Din konto er blevet midlertidigt deaktiveret pga. for mange fejlslagne loginforsøg. Forsøg venligst igen om {count} minutter.' + ERRORNEWPASSWORD: 'Du har indtastet dit nye kodeord forskelligt, forsøg igen' + ERRORPASSWORDNOTMATCH: 'Dit nuværende kodeord matcher ikke, forsøg venligst igen' + ERRORWRONGCRED: 'De indtastede værdier ser ikke ud til at være korrekte. Forsøg venligst igen.' + FIRSTNAME: Fornavn + INTERFACELANG: 'Sprog i brugerfladen' + KEEPMESIGNEDIN: 'Hold mig logget ind' + LOGGEDINAS: 'Du er logget ind som {name}.' + NEWPASSWORD: 'Nyt kodeord' + PASSWORD: Kodeord + PASSWORDEXPIRED: 'Dit kodeord er udløbet. Vælg venligst et nyt.' + PLURALNAME: Brugere + PLURALS: + one: 'En bruger' + other: '{count} brugere' + REMEMBERME: 'Husk mig til næste gang? (i {count} dage på denne enhed)' + SINGULARNAME: Bruger + SUBJECTPASSWORDCHANGED: 'Dit kodeord er blevet ændret' + SUBJECTPASSWORDRESET: 'Link til at nulstille dit kodeord' + SURNAME: Efternavn + VALIDATIONADMINLOSTACCESS: 'Kan ikke fjerne alle admin grupper fra din profil' + ValidationIdentifierFailed: 'Kan ikke overskrive eksisterende bruger #{id} med identisk identifikator ({name} = {value}))' + WELCOMEBACK: 'Velkommen tilbage, {firstname}' + YOUROLDPASSWORD: 'Dit gamle kodeord' + belongs_many_many_Groups: Grupper + db_Locale: 'Sprog i brugerfladen' + db_LockedOutUntil: 'Låst ude indtil' + db_Password: Kodeord + db_PasswordExpiry: Kodeordsudløbsdato + SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: + AUTHENTICATORNAME: 'CMS bruger loginform' + BUTTONFORGOTPASSWORD: 'Glemt kodeord' + BUTTONLOGIN: 'Log mig ind igen' + BUTTONLOGOUT: 'Log ud' + SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: + ERRORWRONGCRED: 'De indtastede værdier ser ikke ud til at være korrekte. Forsøg venligst igen.' + NoPassword: 'Der er ikke en kode på denne bruger.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'Email og kodeord' + SilverStripe\Security\MemberPassword: + PLURALNAME: 'Bruger kodeord' + PLURALS: + one: 'Et bruger kodeord' + other: '{count} bruger kodeord' + SINGULARNAME: 'Bruger kodeord' + SilverStripe\Security\PasswordValidator: + LOWCHARSTRENGTH: 'Forøg venligst kodeordets styrke, ved at tilføje nogle af følgende tegn: {chars}' + PREVPASSWORD: 'Du har tidligere brugt dette kodeord, vælg venligst et nyt kodeord' + TOOSHORT: 'Kodeordet er for kort, det skal mindst være {minimum} eller flere tegn langt' SilverStripe\Security\Permission: + AdminGroup: Administrator + CMS_ACCESS_CATEGORY: 'CMS Adgang' CONTENT_CATEGORY: Indholdsrettigheder + FULLADMINRIGHTS: 'Fuld administrator rettighed' + FULLADMINRIGHTS_HELP: 'Indebærer og overskriver alle andre tildelte rettigheder.' + PERMISSIONS_CATEGORY: 'Roller og adgangsrettigheder' + PLURALNAME: Rettigheder + PLURALS: + one: 'En rettighed' + other: '{count} rettigheder' + SINGULARNAME: Rettighed + UserPermissionsIntro: 'Tildeling af grupper til denne bruger, ændrer de rettigheder brugeren har. Se gruppe området for rettigheds detaljer på de individuelle grupper.' + SilverStripe\Security\PermissionCheckboxSetField: + AssignedTo: 'tildelt til "{title}"' + FromGroup: 'nedarvet fra gruppen "{title}"' + FromRole: 'nedarvet fra rollen "{title}"' + FromRoleOnGroup: 'nedarvet fra rollen "{roletitle}" på gruppen "{grouptitle}"' + SilverStripe\Security\PermissionRole: + OnlyAdminCanApply: 'Kun administratorer kan tilføje' + PLURALNAME: Roller + PLURALS: + one: 'En rolle' + other: '{count} roller' + SINGULARNAME: Rolle + Title: Titel + SilverStripe\Security\PermissionRoleCode: + PLURALNAME: 'Rettigheds rolle koder' + PLURALS: + one: 'En rettigheds rolle kode' + other: '{count} rettigheds rolle koder' + PermsError: 'Kan ikke tildele koden "{code}" med fortrinsrettigheder (kræver ADMIN adgang)' + SINGULARNAME: 'Rettighed rolle kode' + SilverStripe\Security\RememberLoginHash: + PLURALNAME: 'Login hashes' + PLURALS: + one: 'Et login hash' + other: '{count} Login Hashes' + SINGULARNAME: 'Login hash' + SilverStripe\Security\Security: + ALREADYLOGGEDIN: 'Du har ikke adgang til denne side. Hvis du har en anden bruger der har adgang til denne side, kan du logge ind med denne herunder.' + BUTTONSEND: 'Send mig linket til at nulstille kodeordet' + CHANGEPASSWORDBELOW: 'Du kan ændre dit kodeord herunder.' + CHANGEPASSWORDHEADER: 'Skift dit kodeord' + CONFIRMLOGOUT: 'Klik venligst på knappen herunder, for at bekræfte at du vil logge ud.' + ENTERNEWPASSWORD: 'Indtast venligst et nyt kodeord.' + ERRORPASSWORDPERMISSION: 'Du skal være logget ind, for at kunne ændre dit kodeord!' + LOGIN: 'Log ind' + LOGOUT: 'Log ud' + LOSTPASSWORDHEADER: 'Glemt kodeord' + NOTEPAGESECURED: 'Denne side er beskyttet. Indtast dine loginoplysninger herunder for at få adgang.' + NOTERESETPASSWORD: 'Indtast din email adresse, så sender vi dig et link som du kan nulstille dit kodeord med' + PASSWORDRESETSENTHEADER: 'link til at nulstille kodeord afsendt' + PASSWORDRESETSENTTEXT: 'Tak for det. Et link til at nulstille dit kodeord er afsendt, hvis der findes en bruger med denne email adresse.' diff --git a/lang/de.yml b/lang/de.yml index 1e9f16e5e..77e2f1584 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -190,7 +190,4 @@ de: LOGIN: Anmelden LOSTPASSWORDHEADER: 'Passwort vergessen' NOTEPAGESECURED: 'Diese Seite ist geschützt. Bitte melden Sie sich an und Sie werden sofort weitergeleitet.' - NOTERESETLINKINVALID: '

Der Link zum Zurücksetzen des Passworts ist entweder nicht korrekt oder abgelaufen

Sie können einen neuen Link anfordern oder Ihr Passwort nach dem einloggen ändern.

' NOTERESETPASSWORD: 'Geben Sie Ihre E-Mail-Adresse ein und wir werden Ihnen einen Link zuschicken, mit dem Sie Ihr Passwort zurücksetzen können.' - PASSWORDSENTHEADER: 'Der Link zum Zurücksetzen des Passworts wurde an ''{email}'' gesendet' - PASSWORDSENTTEXT: 'Vielen Dank! Wenn ein Account zu der E-Mail Adresse ''{email}'' existiert, wurde eine E-Mail mit dem Link zum Zurücksetzen des Passworts verschickt.' diff --git a/lang/eo.yml b/lang/eo.yml index 59806b953..fb6b74ca9 100644 --- a/lang/eo.yml +++ b/lang/eo.yml @@ -95,6 +95,8 @@ eo: DeletePermissionsFailure: 'Mankas permeso forigi' Deleted: 'Forigita {type} {name}' Save: Konservi + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Redakti SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: UnlinkSelfFailure: 'Ne povas forigi vin el ĉi tiu grupo; vi perdus administrajn rajtojn' SilverStripe\Forms\GridField\GridFieldPaginator: @@ -147,6 +149,8 @@ eo: other: '{count} jaroj' SilverStripe\ORM\FieldType\DBEnum: ANY: Ajna + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'Tro multaj objektoj; retropaŝa kampo uzata' SilverStripe\ORM\Hierarchy: LIMITED_TITLE: 'Tro da idoj ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: @@ -319,7 +323,6 @@ eo: LOGOUT: Elsaluti LOSTPASSWORDHEADER: 'Perdis pasvorton' NOTEPAGESECURED: 'Tiu paĝo estas sekurigita. Enigu viajn akreditaĵojn sube kaj vi aliros pluen.' - NOTERESETLINKINVALID: '

La pasvorta reagorda ligilo estas malvalida aŭ finiĝis.

Vi povas peti novan ĉi tie aŭ ŝanĝi vian pasvorton post vi ensalutis.

' NOTERESETPASSWORD: 'Enigu vian retpoŝtan adreson kaj ni sendos al vi ligilon per kiu vi povas reagordi vian pasvorton' - PASSWORDSENTHEADER: 'Pasvorta reagorda ligilo sendiĝis al ''{email}''' - PASSWORDSENTTEXT: 'Dankon! Reagordita ligilo sendiĝis al ''{email}'', kondiĉe ke konto ekzistas por tiu retadreso.' + PASSWORDRESETSENTHEADER: 'Pasvorta reagorda ligilo sendiĝis' + PASSWORDRESETSENTTEXT: 'Dankon. Reagorda ligilo sendiĝis, kondiĉe ke konto ekzistas por ĉi tiu retadreso.' diff --git a/lang/es.yml b/lang/es.yml index 0009c7a4a..debd4b4a7 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -249,7 +249,4 @@ es: LOGIN: Entrar LOSTPASSWORDHEADER: '¿Contraseña Perdida?' NOTEPAGESECURED: 'Esa página está protegida. Introduzca sus datos de acreditación a continuación y lo enviaremos a ella en un momento.' - NOTERESETLINKINVALID: '

El enlace para restablecer la contraseña es inválido o ha expirado.

Usted puede solicitar uno nuevo aqui o cambiar su contraseña después de que se haya conectado.

' NOTERESETPASSWORD: 'Introduzca su dirección de e-mail, y le enviaremos un enlace, con el cual podrá restaurar su contraseña' - PASSWORDSENTHEADER: 'Un enlace para restablecer la contraseña ha sido enviado a ''{email}''' - PASSWORDSENTTEXT: 'Gracias! Un enlace para restablecer la contraseña ha sido enviado a ''{email}'', siempre que una cuenta exista para la dirección de email indicada.' diff --git a/lang/et_EE.yml b/lang/et_EE.yml index 63fc4cd5d..a8fb3b686 100644 --- a/lang/et_EE.yml +++ b/lang/et_EE.yml @@ -139,7 +139,4 @@ et_EE: ERRORPASSWORDPERMISSION: 'Pead olema sisseloginud, et parooli muuta!' LOGIN: 'Logi sisse' NOTEPAGESECURED: 'See leht on turvatud. Sisesta enda andmed allpool ja me saadame sind otse edasi' - NOTERESETLINKINVALID: '

Parooli lähtestamise link on kehtetu või aegunud.

Saate taotleda uut linki siin või muuta parooli pärast sisselogimist.

' NOTERESETPASSWORD: 'Sisesta oma email ja me saadame sulle lingi kus saad oma parooli tühistada.' - PASSWORDSENTHEADER: 'Parooli lähtestamise link saadeti aadressile ''{email}''' - PASSWORDSENTTEXT: 'Aitäh! Lähtestamislink saadeti aadressile ''{email}'' eeldusel, et selle e-posti aadressiga seotud konto on olemas.' diff --git a/lang/fa_IR.yml b/lang/fa_IR.yml index b292b25d7..b9aa0ebea 100644 --- a/lang/fa_IR.yml +++ b/lang/fa_IR.yml @@ -168,4 +168,3 @@ fa_IR: ERRORPASSWORDPERMISSION: 'جهت تغییر گذرواژه خود باید وارد شده باشید!' LOGIN: ورود LOSTPASSWORDHEADER: 'فراموشی گذرواژه' - PASSWORDSENTHEADER: 'لینک ازنوسازی گذرواژه به ''{email}'' ارسال شد' diff --git a/lang/fi.yml b/lang/fi.yml index 364762d3a..7f8579e7f 100644 --- a/lang/fi.yml +++ b/lang/fi.yml @@ -95,6 +95,8 @@ fi: DeletePermissionsFailure: 'Ei oikeuksia poistamiseen' Deleted: 'Poistettiin {type} {name}' Save: Tallenna + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Muokkaa SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: UnlinkSelfFailure: 'Et voi siirtää itseäsi pois tästä ryhmästä: menettäisit pääkäyttäjän oikeudet' SilverStripe\Forms\GridField\GridFieldPaginator: @@ -147,6 +149,8 @@ fi: other: '{count} vuotta' SilverStripe\ORM\FieldType\DBEnum: ANY: Yhtään + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'Liian monta samaan liittyvää objektia: oletuskenttä käytössä' SilverStripe\ORM\Hierarchy: LIMITED_TITLE: 'Liian monta lapsiobjektia ({count}}' SilverStripe\ORM\Hierarchy\Hierarchy: @@ -197,6 +201,7 @@ fi: many_many_Members: Jäsenet SilverStripe\Security\LoginAttempt: Email: Sähköpostiosoite + EmailHashed: 'Sähköpostiosoite (tiivistetty)' IP: IP-osoite PLURALNAME: Kirjautumisyritykset PLURALS: @@ -255,6 +260,8 @@ fi: SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: ERRORWRONGCRED: 'Antamasi tiedot eivät näytä oikeilta. Yritä uudelleen.' NoPassword: 'Tällä käyttäjällä ei ole salasanaa' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'Sähköpostiosoite & salasana' SilverStripe\Security\MemberPassword: PLURALNAME: 'Käyttäjän salasanat' PLURALS: @@ -318,5 +325,5 @@ fi: NOTEPAGESECURED: 'Tämä sivu on suojattu. Syötä tunnistetietosi alle niin pääset eteenpäin.' NOTERESETLINKINVALID: '

Salasanan palautuslinkki on virheellinen tai vanhentunut.

Voit pyytää uuden napsauttamalla tästä tai vaihtaa salasanasi kirjautumisen jälkeen.

' NOTERESETPASSWORD: 'Syötä sähköpostiosoitteesi ja lähetämme sinulle linkin, jonka avulla saat palautettua salasanasi' - PASSWORDSENTHEADER: 'Salasanan palautuslinkki lähetettiin osoitteeseen ''{email}''' - PASSWORDSENTTEXT: 'Kiitos! Salasanan palautuslinkki lähetettiin osoitteeseen ''{email}'', joka on liitettynä tähän käyttäjätiliin.' + PASSWORDRESETSENTHEADER: 'Salasanan palautuslinkki lähetetty' + PASSWORDRESETSENTTEXT: 'Kiitos, palautuslinkki on lähetetty käyttäjätilille asetettuun sähköpostiosoitteeseen.' diff --git a/lang/fr.yml b/lang/fr.yml index 15b6dab42..450cfdb87 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -319,7 +319,4 @@ fr: LOGOUT: 'Se déconnecter' LOSTPASSWORDHEADER: 'Mot de passe oublié' NOTEPAGESECURED: 'Cette page est sécurisée. Entrez vos identifiants ci-dessous et vous pourrez y avoir accès.' - NOTERESETLINKINVALID: '

Le lien de réinitialisation du mot de passe n’est pas valide ou a expiré.

Vous pouvez en demander un nouveau en suivant ce lien ou changer de mot de passe après connexion.

' NOTERESETPASSWORD: 'Entrez votre adresse email et nous vous enverrons un lien pour modifier votre mot de passe' - PASSWORDSENTHEADER: "Lien de réinitialisation de mot de passe envoyé à «\_{email}\_»" - PASSWORDSENTTEXT: "Merci\_! Un lien de réinitialisation vient d’être envoyé à «\_{email}\_», à condition que cette adresse existe." diff --git a/lang/id.yml b/lang/id.yml index d17eac338..c9c06bbff 100644 --- a/lang/id.yml +++ b/lang/id.yml @@ -167,7 +167,4 @@ id: LOGIN: Masuk LOSTPASSWORDHEADER: 'Kata Kunci yang Terlupa' NOTEPAGESECURED: 'Laman ini diamankan. Isikan data berikut untuk dikirimkan hak akses Anda.' - NOTERESETLINKINVALID: '

Tautan penggantian kata kunci tidak valid atau sudah kadaluarsa.

Anda dapat meminta yang baru di sini atau mengganti kata kunci setelah Anda masuk.

' NOTERESETPASSWORD: 'Isikan alamat email Anda untuk mendapatkan tautan penggantian kata kunci' - PASSWORDSENTHEADER: 'Tautan penggantian kata kunci dikirimkan ke ''{email}''' - PASSWORDSENTTEXT: 'Terimakasih! Tautan reset telah dikirim ke ''{email}'', berisi informasi akun untuk alamat email ini.' diff --git a/lang/id_ID.yml b/lang/id_ID.yml index 22ebcb2e5..11d1f2bb3 100644 --- a/lang/id_ID.yml +++ b/lang/id_ID.yml @@ -166,7 +166,4 @@ id_ID: LOGIN: Masuk LOSTPASSWORDHEADER: 'Kata Kunci yang Terlupa' NOTEPAGESECURED: 'Laman ini diamankan. Isikan data berikut untuk dikirimkan hak akses Anda.' - NOTERESETLINKINVALID: '

Tautan penggantian kata kunci tidak valid atau sudah kadaluarsa.

Anda dapat meminta yang baru di sini atau mengganti kata kunci setelah Anda masuk.

' NOTERESETPASSWORD: 'Isikan alamat email Anda untuk mendapatkan tautan penggantian kata kunci' - PASSWORDSENTHEADER: 'Tautan penggantian kata kunci dikirimkan ke ''{email}''' - PASSWORDSENTTEXT: 'Terimakasih! Tautan reset telah dikirim ke ''{email}'', berisi informasi akun untuk alamat email ini.' diff --git a/lang/it.yml b/lang/it.yml index 05bf5dc83..4089faf9b 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -95,6 +95,10 @@ it: DeletePermissionsFailure: 'Non hai i permessi per eliminare' Deleted: 'Eliminato {type} {name}' Save: Salva + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Modifica + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Non è possibile rimuovere te stesso da questo gruppo, perderesti i diritti di admin' SilverStripe\Forms\GridField\GridFieldPaginator: OF: di Page: Pagina @@ -145,6 +149,8 @@ it: other: '{count} anni' SilverStripe\ORM\FieldType\DBEnum: ANY: Qualsiasi + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'Troppi oggetti correlati; campo di fallback in uso' SilverStripe\ORM\Hierarchy: LIMITED_TITLE: 'Troppi figli ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: @@ -195,6 +201,7 @@ it: many_many_Members: Membri SilverStripe\Security\LoginAttempt: Email: 'Indirizzo e-mail' + EmailHashed: 'Indirizzo email (hash)' IP: 'Indirizzo IP' PLURALNAME: 'Tentativi d''accesso' PLURALS: @@ -236,6 +243,7 @@ it: SUBJECTPASSWORDCHANGED: 'La tua password è stata cambiata' SUBJECTPASSWORDRESET: 'Link per azzerare la tua password' SURNAME: Cognome + VALIDATIONADMINLOSTACCESS: 'Non è possibile rimuovere tutti i gruppi admin dal tuo profilo' ValidationIdentifierFailed: 'Non posso sovrascrivere l''utente esistente #{id} con identificatore identico ({name} = {value}))' WELCOMEBACK: 'Bentornato, {firstname}' YOUROLDPASSWORD: 'La tua vecchia password' @@ -252,6 +260,8 @@ it: SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: ERRORWRONGCRED: 'I dettagli forniti non sembrano corretti. Per favore riprovare.' NoPassword: 'Manca la password per questo utente.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'E-mail & Password' SilverStripe\Security\MemberPassword: PLURALNAME: 'Password utenti' PLURALS: @@ -313,7 +323,6 @@ it: LOGOUT: Scollegati LOSTPASSWORDHEADER: 'Password smarrita' NOTEPAGESECURED: 'La pagina è protetta. Inserisci le credenziali qui sotto per poter andare avanti.' - NOTERESETLINKINVALID: '

Il link per azzerare la password non è valido o è scaduto.

Puoi richiederne uno nuovo qui o cambiare la tua password dopo che ti sei connesso.

' NOTERESETPASSWORD: 'Inserisci il tuo indirizzo e-mail e ti verrà inviato un link per poter azzerare la tua password.' - PASSWORDSENTHEADER: 'Link per azzeramento della password inviato a ''{email}''' - PASSWORDSENTTEXT: 'Grazie! Un link di azzeramento è stato inviato a ''{email}'', fornito un account esistente per questo indirizzo e-mail.' + PASSWORDRESETSENTHEADER: 'Link di azzeramento password inviato' + PASSWORDRESETSENTTEXT: 'Grazie! Un link di azzeramento è stato inviato, supponendo un account esista a quell''indirizzo e-mail.' diff --git a/lang/ja.yml b/lang/ja.yml index b2f92eb1e..433a832e2 100644 --- a/lang/ja.yml +++ b/lang/ja.yml @@ -146,7 +146,4 @@ ja: ERRORPASSWORDPERMISSION: パスワードを変更する為に、ログインしなければなりません! LOGIN: ログイン NOTEPAGESECURED: このページはセキュリティで保護されております証明書キーを下記に入力してください。こちらからすぐに送信します - NOTERESETLINKINVALID: '

パスワードのリセットリンクは有効でないか期限切れです。

新しいパスワードを要求することができます ここ もしくはパスワードを変更することができます ログインした後 .

' NOTERESETPASSWORD: メールアドレスを入力してください、パスワードをリセットするURLを送信致します - PASSWORDSENTHEADER: 'パスワードリセットリンクは ''{email}'' に送信されました' - PASSWORDSENTTEXT: 'ありがとうございました! リセットリンクは、''{email}'' に、このアカウントが存在することを前提として送信されました。' diff --git a/lang/lt.yml b/lang/lt.yml index abdbaea25..3ca7adbff 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -167,7 +167,4 @@ lt: LOGIN: Prisijungti LOSTPASSWORDHEADER: 'Slaptažodžio atstatymas' NOTEPAGESECURED: 'Šis puslapis yra apsaugotas. Įveskite savo duomenis į žemiau esančius laukelius.' - NOTERESETLINKINVALID: '

Neteisinga arba negaliojanti slaptažodžio atstatymo nuoroda.

Galite atsisiųsti naują čia arba pasikeisti slaptažodį po to, kai prisijungsite.

' NOTERESETPASSWORD: 'Įveskite savo e. pašto adresą ir atsiųsime slaptažodžio atstatymui skirtą nuorodą' - PASSWORDSENTHEADER: 'Slaptažodžio atstatymo nuoroda nusiųsta į ''{email}''' - PASSWORDSENTTEXT: 'Atstatymo nuoroda nusiųsta į ''{email}''' diff --git a/lang/mi.yml b/lang/mi.yml index 7a2601ed5..e9fe2308e 100644 --- a/lang/mi.yml +++ b/lang/mi.yml @@ -149,7 +149,4 @@ mi: LOGIN: Takiuru LOSTPASSWORDHEADER: 'Kupuhipa Ngaro' NOTEPAGESECURED: 'Kua ngita tēnā whārangi. Tāurua ō taipitoptio tuakiri ki raro, ā, mā mātou koe e tuku kia haere tonu.' - NOTERESETLINKINVALID: '

He muhu, kua mōnehu rānei te hono tautuhi kupuhipa anō.

Ka taea te tono i te mea hōui konei ka huri rānei i tō kupuhipa ā muri i tōtakiuru.

' NOTERESETPASSWORD: 'Tāurua tō wāhitau īmēra, mā mātou e tuku tētahi hono ki a koe e taea ai te tautuhi anō i tō kupuhipa' - PASSWORDSENTHEADER: 'I tukuna he hono tautuhi kupuhipa anō ki ''{email}''' - PASSWORDSENTTEXT: 'Kia ora! Kua tukuna he hono tautuhi anō ki ''{email}'',engari rā kei te tīariari he pūkete mō taua wāhitau īmēra.' diff --git a/lang/nb.yml b/lang/nb.yml index 91dd9f758..f1dc4c74d 100644 --- a/lang/nb.yml +++ b/lang/nb.yml @@ -152,7 +152,4 @@ nb: LOGIN: 'Logg inn' LOSTPASSWORDHEADER: 'Mistet passord' NOTEPAGESECURED: 'Den siden er sikret. Skriv inn gyldig innloggingsinfo så kommer du inn.' - NOTERESETLINKINVALID: '

Lenken for å nullstille passordet er ugyldig eller utgått.

Du kan kreve en ny her eller endre passordet etter at du har logget inn.

' NOTERESETPASSWORD: 'Skriv inn epostadressen din og vi vil sende deg en lenke som nullstiller passordet.' - PASSWORDSENTHEADER: 'Lenke for nullstilling av passord ble sendt til ''{email}''' - PASSWORDSENTTEXT: 'Takk! En lenke for å lage nytt passord er sendt til ''{email}'', forutsatt at det eksisterer en konto for denne epostadressen.' diff --git a/lang/nl.yml b/lang/nl.yml index 64f191213..242eccc45 100644 --- a/lang/nl.yml +++ b/lang/nl.yml @@ -1,4 +1,26 @@ nl: + SilverStripe\Admin\LeftAndMain: + VersionUnknown: onbekend + SilverStripe\AssetAdmin\Forms\UploadField: + Dimensions: Afmetingen + EDIT: Bewerken + EDITINFO: 'Bewerk dit bestand' + REMOVE: Verwijder + SilverStripe\Control\ChangePasswordEmail_ss: + CHANGEPASSWORDFOREMAIL: 'Het wachtwoord voor het account met e-mailadres {email} is aangepast. Indien u uw wachtwoord niet heeft aangepast kunt u dat doen met onderstaande link.' + CHANGEPASSWORDTEXT1: 'U heeft het wachtwoord veranderd voor' + CHANGEPASSWORDTEXT3: 'Wachtwoord veranderen' + HELLO: Hallo + SilverStripe\Control\Email\ForgotPasswordEmail_ss: + HELLO: Hallo + TEXT1: 'Hier is uw' + TEXT2: 'link om uw wachtwoord opnieuw aan te maken' + TEXT3: voor + SilverStripe\Control\RequestProcessor: + INVALID_REQUEST: 'Fout bij verwerken' + REQUEST_ABORTED: 'Fout bij verwerken (geannuleerd)' + SilverStripe\Core\Manifest\VersionProvider: + VERSIONUNKNOWN: Onbekend SilverStripe\Forms\CheckboxField: NOANSWER: Nee YESANSWER: Ja @@ -8,6 +30,8 @@ nl: ATLEAST: 'Een wachtwoord moet tenminste {min} karakters hebben.' BETWEEN: 'Een wachtwoord moet tussen de {min} en {max} karakters hebben' CURRENT_PASSWORD_ERROR: 'Het wachtwoord dat u heeft ingevoerd is niet juist.' + CURRENT_PASSWORD_MISSING: 'Voer uw huidige wachtwoord in.' + LOGGED_IN_ERROR: 'U moet ingelogd zijn om uw wachtwoord te kunnen veranderen!' MAXIMUM: 'Een wachtwoord mag maximaal {max} karakters hebben.' SHOWONCLICKTITLE: 'Verander wachtwoord' SilverStripe\Forms\CurrencyField: @@ -16,12 +40,20 @@ nl: VALIDDATEFORMAT2: 'Vul een geldig datumformaat in ({format})' VALIDDATEMAXDATE: 'De datum moet ouder of gelijk zijn aan de maximale datum ({date})' VALIDDATEMINDATE: 'De datum moet nieuwer of gelijk zijn aan de minimale datum ({date})' + SilverStripe\Forms\DatetimeField: + VALIDDATEMAXDATETIME: 'De datum moet ouder of gelijk zijn aan de maximale datum ({datetime})' + VALIDDATETIMEFORMAT: 'Vul een geldige datum in ({format})' + VALIDDATETIMEMINDATE: 'De datum moet nieuwer of gelijk zijn aan de minimale datum ({datetime})' SilverStripe\Forms\DropdownField: CHOOSE: (Kies) + CHOOSE_MODEL: '(Selecteer {name})' SOURCE_VALIDATION: 'Selecteer een optie uit de lijst. {value} is geen geldige keuze.' SilverStripe\Forms\EmailField: VALIDATION: 'Gelieve een e-mailadres in te voeren.' + SilverStripe\Forms\FileUploadReceiver: + FIELDNOTSET: 'Bestandsinformatie niet gevonden' SilverStripe\Forms\Form: + BAD_METHOD: 'Dit formulier moet middels {method} verzonden worden' CSRF_EXPIRED_MESSAGE: 'Uw sessie is verlopen. Verzend het formulier opnieuw.' CSRF_FAILED_MESSAGE: 'Er lijkt een technisch probleem te zijn. Klik op de knop terug, vernieuw uw browser, en probeer het opnieuw.' VALIDATIONPASSWORDSDONTMATCH: 'Wachtwoorden komen niet overeen' @@ -30,7 +62,10 @@ nl: VALIDATOR: Validator VALIDCURRENCY: 'Vul een geldige munteenheid in' SilverStripe\Forms\FormField: + EXAMPLE: 'bijv. {format}' NONE: geen + SilverStripe\Forms\FormScaffolder: + TABMAIN: Hoofdgedeelte SilverStripe\Forms\GridField\GridField: Add: '{name} toevoegen' CSVEXPORT: 'Exporteer naar CSV' @@ -60,27 +95,67 @@ nl: DeletePermissionsFailure: 'Onvoldoende rechten om te verwijderen' Deleted: '{type} {name} verwijderd' Save: Opslaan + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Bewerken + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'U kunt uzelf niet verwijderen van deze groep, omdat u dan geen admin-rechten meer heeft.' + SilverStripe\Forms\GridField\GridFieldPaginator: + OF: van + Page: Pagina + View: Bekijk SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Aantal FIELDLABELCURRENCY: Munteenheid + INVALID_CURRENCY: 'Valuta {currency} is niet toegestaan' + SilverStripe\Forms\MultiSelectField: + SOURCE_VALIDATION: 'Selecteer een optie uit de lijst. {value} is geen geldige keuze.' SilverStripe\Forms\NullableField: IsNullLabel: 'Is null' SilverStripe\Forms\NumericField: VALIDATION: '''{value}'' is geen getal, enkel getallen worden door dit veld geaccepteerd' SilverStripe\Forms\TimeField: VALIDATEFORMAT: 'Vul een geldig datumformaat in ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: 'Data objecten' + PLURALS: + one: 'Data object' + other: '{count} Data objecten' + SINGULARNAME: 'Data object' SilverStripe\ORM\FieldType\DBBoolean: ANY: Elke NOANSWER: Nee YESANSWER: Ja SilverStripe\ORM\FieldType\DBDate: + DAYS_SHORT_PLURALS: + one: '{count} dag' + other: '{count} dagen' + HOURS_SHORT_PLURALS: + one: '{count} uur' + other: '{count} uren' LessThanMinuteAgo: 'minder dan één minuut' + MINUTES_SHORT_PLURALS: + one: '{count} minuut' + other: '{count} minuten' + MONTHS_SHORT_PLURALS: + one: '{count} maand' + other: '{count} maanden' + SECONDS_SHORT_PLURALS: + one: '{count} seconde' + other: '{count} seconden' TIMEDIFFAGO: '{difference} geleden' TIMEDIFFIN: 'in {difference}' + YEARS_SHORT_PLURALS: + one: '{count} jaar' + other: '{count} jaren' SilverStripe\ORM\FieldType\DBEnum: ANY: Elke + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'Teveel keuzes in de lijst; een alternatief veld wordt getoond.' + SilverStripe\ORM\Hierarchy: + LIMITED_TITLE: 'Teveel onderliggende items ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: InfiniteLoopNotAllowed: 'Oneindige lus gevonden in "{type}" hiërarchie. Wijzig het hogere niveau om dit op te lossen' + LIMITED_TITLE: 'Teveel onderliggende items ({count})' SilverStripe\ORM\ValidationException: DEFAULT_ERROR: Validatiefout SilverStripe\Security\BasicAuth: @@ -91,34 +166,60 @@ nl: PASSWORDEXPIRED: '

Uw wachtwoord is verlopen. Kies een nieuw wachtwoord.

' SilverStripe\Security\CMSSecurity: INVALIDUSER: '

Ongeldige gebruiker Log hier opnieuw in om verder te gaan.

' + LOGIN_MESSAGE: 'Sessie is verlopen' + LOGIN_TITLE: '

U kunt verder met wat u aan het doen was, door opnieuw in te loggen.

' SUCCESS: Succes SUCCESSCONTENT: '

U bent ingelogd. Klik hier als u niet automatisch wordt doorgestuurd.

' + SUCCESS_TITLE: 'Inloggen is gelukt' + SilverStripe\Security\DefaultAdminService: + DefaultAdminFirstname: 'Standaard Beheerder' SilverStripe\Security\Group: AddRole: 'Voeg een rol toe aan deze groep' Code: 'Groep code' DefaultGroupTitleAdministrators: Beheerders DefaultGroupTitleContentAuthors: 'Inhoud Auteurs' Description: 'Omschrijving ' + GROUPNAME: 'Groep naam' GroupReminder: 'Als u de bovenliggende groep selecteert, neemt deze groep alle rollen over' HierarchyPermsError: 'U moet (ADMIN) rechten hebben om de bovenliggende groep "{group}" toe te kennen' Locked: 'Gesloten?' + MEMBERS: Leden + NEWGROUP: 'Nieuwe groep' NoRoles: 'Geen rollen gevonden' + PERMISSIONS: Rechten + PLURALNAME: Groepen + PLURALS: + one: 'Een groep' + other: '{count} groepen' Parent: 'Bovenliggende groep' + ROLES: Rollen + ROLESDESCRIPTION: 'Rollen zijn logische groeperingen van rechten die in het Rollen tabblad gewijzigd kunnen worden.
Rollen worden automatisch overgenomen van bovenliggende groepen.' RolesAddEditLink: 'Rollen beheren' + SINGULARNAME: Groep Sort: Sorteer-richting has_many_Permissions: Rechten many_many_Members: Leden SilverStripe\Security\LoginAttempt: + Email: 'E-mailadres ' + EmailHashed: 'E-mailadres (versleuteld)' IP: 'IP adres' + PLURALNAME: Inlogpogingen + PLURALS: + one: 'Een inlogpoging' + other: '{count} inlogpogingen' + SINGULARNAME: Inlogpogingen Status: Status SilverStripe\Security\Member: ADDGROUP: 'Groep toevoegen' BUTTONCHANGEPASSWORD: 'Wachtwoord veranderen' BUTTONLOGIN: Inloggen BUTTONLOGINOTHER: 'Als iemand anders inloggen' + BUTTONLOGOUT: Uitloggen BUTTONLOSTPASSWORD: 'Ik ben mijn wachtwoord vergeten' CONFIRMNEWPASSWORD: 'Bevestig het nieuwe wachtwoord' CONFIRMPASSWORD: 'Bevestig wachtwoord' + CURRENT_PASSWORD: 'Huidige wachtwoord' + EDIT_PASSWORD: 'Nieuw wachtwoord' EMAIL: E-mail EMPTYNEWPASSWORD: 'Het nieuwe wachtwoord mag niet leeg zijn, probeer opnieuw' ENTEREMAIL: 'Typ uw e-mailadres om een link te ontvangen waarmee u uw wachtwoord kunt resetten.' @@ -128,13 +229,21 @@ nl: ERRORWRONGCRED: 'De ingevulde gegevens lijken niet correct. Probeer het nog een keer.' FIRSTNAME: Voornaam INTERFACELANG: 'Interface taal' + KEEPMESIGNEDIN: 'Houd mij ingelogd' LOGGEDINAS: 'U bent ingelogd als {name}.' NEWPASSWORD: 'Nieuw wachtwoord' PASSWORD: Wachtwoord PASSWORDEXPIRED: 'Uw wachtwoord is verlopen. Kies een nieuw wachtwoord.' + PLURALNAME: Leden + PLURALS: + one: 'Een lid' + other: '{count} leden' + REMEMBERME: 'Onthoud mij voor volgende keer? (voor {count} dagen op dit apparaat)' + SINGULARNAME: Lid SUBJECTPASSWORDCHANGED: 'Uw wachtwoord is veranderd' SUBJECTPASSWORDRESET: 'Link om uw wachtwoord opnieuw aan te maken' SURNAME: Achternaam + VALIDATIONADMINLOSTACCESS: 'Niet mogelijk om alle admin-groepen te verwijderen van uw profiel' ValidationIdentifierFailed: 'Een bestaande gebruiker #{id} kan niet dezelfde unieke velden hebben ({name} = {value}))' WELCOMEBACK: 'Welkom terug, {firstname}' YOUROLDPASSWORD: 'Uw oude wachtwoord' @@ -143,15 +252,38 @@ nl: db_LockedOutUntil: 'Gesloten tot' db_Password: Wachtwoord db_PasswordExpiry: 'Wachtwoord vervaldatum' + SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: + AUTHENTICATORNAME: Inlogformulier + BUTTONFORGOTPASSWORD: 'Wachtwoord vergeten' + BUTTONLOGIN: 'Opnieuw inloggen' + BUTTONLOGOUT: Uitloggen + SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: + ERRORWRONGCRED: 'De ingevulde gegevens lijken niet correct. Probeer het nog een keer.' + NoPassword: 'Er is geen wachtwoord voor deze gebruiker.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'E-mail & wachtwoord' + SilverStripe\Security\MemberPassword: + PLURALNAME: Gebruikerswachtwoorden + PLURALS: + one: 'Een gebruikerswachtwoord' + other: '{count} Gebruikerswachtwoorden' + SINGULARNAME: Gebruikerswachtwoord SilverStripe\Security\PasswordValidator: LOWCHARSTRENGTH: 'Maak a.u.b. uw wachtwoord sterker door enkele van de volgende karakters te gebruiken: {chars}' PREVPASSWORD: 'U heeft dit wachtwoord in het verleden al gebruikt, kies a.u.b. een nieuw wachtwoord.' TOOSHORT: 'Het wachtwoord is te kort, het moet minimaal {minimum} karakters hebben' SilverStripe\Security\Permission: AdminGroup: Beheerder + CMS_ACCESS_CATEGORY: 'CMS toegang' CONTENT_CATEGORY: Inhoudsrechten FULLADMINRIGHTS: 'Volledige admin rechten' FULLADMINRIGHTS_HELP: 'Impliceert en overstemt alle andere toegewezen rechten.' + PERMISSIONS_CATEGORY: 'Rollen en toegangsrechten' + PLURALNAME: Rechten + PLURALS: + one: Machtiging + other: '{count} rechten' + SINGULARNAME: Machtiging UserPermissionsIntro: 'Groepen aan deze gebruiker toewijzen zullen diens permissies aanpassen. Zie de sectie Groepen voor meer informatie over machtigingen voor afzonderlijke groepen.' SilverStripe\Security\PermissionCheckboxSetField: AssignedTo: 'toegewezen aan "{title}"' @@ -161,21 +293,37 @@ nl: SilverStripe\Security\PermissionRole: OnlyAdminCanApply: 'Alleen admin kan doorvoeren' PLURALNAME: Rollen + PLURALS: + one: 'Een rol' + other: '{count} rollen' SINGULARNAME: Rol Title: Titel SilverStripe\Security\PermissionRoleCode: + PLURALNAME: 'Permissie codes' + PLURALS: + one: 'Een permissiecode' + other: '{count} permissiecodes' PermsError: 'U moet (ADMIN) rechten hebben om de code "{code}" toe te kennen' + SINGULARNAME: Permissiecode + SilverStripe\Security\RememberLoginHash: + PLURALNAME: 'Versleutelde logins' + PLURALS: + one: 'Een versleutelde login' + other: '{count} versleutelde logins' + SINGULARNAME: 'Versleutelde login' SilverStripe\Security\Security: ALREADYLOGGEDIN: 'U hebt geen toegang tot deze pagina. Als u een andere account met de nodige rechten hebt, kan u hieronder opnieuw inloggen.' BUTTONSEND: 'Nieuw wachtwoord aanmaken' CHANGEPASSWORDBELOW: 'U kunt uw wachtwoord hieronder veranderen.' CHANGEPASSWORDHEADER: 'Verander uw wachtwoord' + CONFIRMLOGOUT: 'Klik op onderstaande knop om uit te loggen.' ENTERNEWPASSWORD: 'Voer een nieuw wachtwoord in.' ERRORPASSWORDPERMISSION: 'U moet ingelogd zijn om uw wachtwoord te kunnen veranderen!' LOGIN: 'Meld aan' + LOGOUT: Uitloggen LOSTPASSWORDHEADER: 'Wachtwoord vergeten' NOTEPAGESECURED: 'Deze pagina is beveiligd. Voer uw gegevens in en u wordt automatisch doorgestuurd.' - NOTERESETLINKINVALID: '

De link om uw wachtwoord te kunnen wijzigen is niet meer geldig.

U kunt een nieuwe link aanvragen of uw wachtwoord aanpassen door in te loggen.

' + NOTERESETLINKINVALID: '

De reset link is ongeldig of komen te vervallen.

Je kan hier een nieuwe link aanvragen of het wachtwoord veranderen nadat je bent ingelogd.

' NOTERESETPASSWORD: 'Voer uw e-mailadres in en we sturen een link waarmee u een nieuw wachtwoord kunt instellen.' - PASSWORDSENTHEADER: 'Wachtwoord herstel link verzonden naar {email}' - PASSWORDSENTTEXT: 'Bedankt! Er is een link verstuurd naar {email} om uw wachtwoord opnieuw in te stellen, in de veronderstelling dat er een account bestaat voor dit e-mailadres.' + PASSWORDRESETSENTHEADER: 'link om uw wachtwoord opnieuw aan te maken' + PASSWORDRESETSENTTEXT: 'Bedankt! Er is een link verstuurd om uw wachtwoord opnieuw in te stellen (mits het mailadres reeds bekend is bij ons).' diff --git a/lang/pl.yml b/lang/pl.yml index c0359c922..1905acb38 100644 --- a/lang/pl.yml +++ b/lang/pl.yml @@ -1,7 +1,37 @@ pl: + SilverStripe\Admin\LeftAndMain: + VersionUnknown: Nieznany + SilverStripe\AssetAdmin\Forms\UploadField: + Dimensions: Rozmiar + EDIT: Edytuj + EDITINFO: 'Edytuj plik' + REMOVE: Usuń + SilverStripe\Control\ChangePasswordEmail_ss: + CHANGEPASSWORDFOREMAIL: 'Hasło do konta o adresie e-mail {email} zostało zmienione. Jeśli nie zmieniłeś swojego hasła, zmień hasło, korzystając z poniższego linku' + CHANGEPASSWORDTEXT1: 'Zmieniłeś hasło na' + CHANGEPASSWORDTEXT3: 'Zmień hasło' + HELLO: 'Witaj,' + SilverStripe\Control\Email\ForgotPasswordEmail_ss: + HELLO: 'Witaj,' + TEXT1: 'Oto twój' + TEXT2: 'link zmiany hasła' + TEXT3: dla + SilverStripe\Control\RequestProcessor: + INVALID_REQUEST: 'Nieprawidłowe żądanie' + REQUEST_ABORTED: 'Żądanie zostało przerwane' + SilverStripe\Core\Manifest\VersionProvider: + VERSIONUNKNOWN: Nieznany + SilverStripe\Forms\CheckboxField: + NOANSWER: Nie + YESANSWER: Tak + SilverStripe\Forms\CheckboxSetField_ss: + NOOPTIONSAVAILABLE: 'Brak dostępnych opcji' SilverStripe\Forms\ConfirmedPasswordField: ATLEAST: 'Hasła muszą mieć przynajmniej {min} znaków.' BETWEEN: 'Hasła muszą mieć długość pomiędzy {min} a {max} znaków.' + CURRENT_PASSWORD_ERROR: 'Podane hasło jest nieprawidłowe' + CURRENT_PASSWORD_MISSING: 'Musisz podać swoje aktualne hasło.' + LOGGED_IN_ERROR: 'Musisz być zalogowany aby zmienić hasło' MAXIMUM: 'Hasła mogą mieć co najwyżej {max} znaków.' SHOWONCLICKTITLE: 'Zmiana Hasła' SilverStripe\Forms\CurrencyField: @@ -10,23 +40,38 @@ pl: VALIDDATEFORMAT2: 'Proszę wprowadź prawidłowy format daty ({format})' VALIDDATEMAXDATE: 'Twoja data musi być wcześniejsza lub taka sama, jak maksymalna dozwolona data ({date})' VALIDDATEMINDATE: 'Twoja data musi być późniejsza lub taka sama, jak minimalna dozwolona data ({date})' + SilverStripe\Forms\DatetimeField: + VALIDDATEMAXDATETIME: 'Twoja data musi być wcześniejsza lub taka sama, jak maksymalna dozwolona data ({date})' + VALIDDATETIMEFORMAT: 'Proszę wprowadź prawidłowy format czasu ({format})' + VALIDDATETIMEMINDATE: 'Twoja data musi być późniejsza lub taka sama, jak minimalna dozwolona data ({date})' SilverStripe\Forms\DropdownField: CHOOSE: (wybierz) + CHOOSE_MODEL: '(Wybierz {name})' + SOURCE_VALIDATION: 'Wybierz wartość z podanej listy. {value} nie jest poprawną opcją' SilverStripe\Forms\EmailField: VALIDATION: 'Proszę podaj adres e-mail' + SilverStripe\Forms\FileUploadReceiver: + FIELDNOTSET: 'Nie znaleziono informacji o pliku' SilverStripe\Forms\Form: + BAD_METHOD: 'Ten formularz wymaga {metody} przesłania' + CSRF_EXPIRED_MESSAGE: 'Twoja sesja wygasła. Prześlij ponownie formularz.' + CSRF_FAILED_MESSAGE: 'Wygląda na to, że wystąpił błąd techniczny. Kliknij przycisk wstecz, następnie odśwież przeglądarkę aby wczytać stronę ponownie.' VALIDATIONPASSWORDSDONTMATCH: 'Hasła nie są takie same' VALIDATIONPASSWORDSNOTEMPTY: 'Hasło nie może być puste' VALIDATIONSTRONGPASSWORD: 'Hasła muszą mieć przynajmniej jedną cyfrę oraz jeden znak alfanumeryczny.' VALIDATOR: Walidator VALIDCURRENCY: 'Proszę podaj prawidłową walutę' SilverStripe\Forms\FormField: + EXAMPLE: 'na przykład {format}' NONE: brak + SilverStripe\Forms\FormScaffolder: + TABMAIN: Główny SilverStripe\Forms\GridField\GridField: Add: 'Dodaj {name}' CSVEXPORT: 'Eksportuj do CSV' + CSVIMPORT: 'Import z CSV' Filter: Filtr - FilterBy: 'Filtruj wg' + FilterBy: 'Filtruj wg ' Find: Wyszukaj LinkExisting: 'Linkuj istniejący' NewRecord: 'Nowy {type}' @@ -50,55 +95,145 @@ pl: DeletePermissionsFailure: 'Brak uprawnień do usuwania' Deleted: 'Usunięto {type} {name}' Save: Zapisz + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Nie możesz usunąć siebie z tej grupy, stracone zostałby prawa administratora' + SilverStripe\Forms\GridField\GridFieldPaginator: + OF: z + Page: Strona + View: Widok SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Ilość FIELDLABELCURRENCY: waluta + INVALID_CURRENCY: 'Waluta {currency} nie znajduje się na liście dozwolonych walut' + SilverStripe\Forms\MultiSelectField: + SOURCE_VALIDATION: 'Wybierz wartości z podanej listy. Podano niepoprawną opcję {value}' SilverStripe\Forms\NullableField: IsNullLabel: 'Jest Pusty' SilverStripe\Forms\NumericField: VALIDATION: '''{value}'' nie jest liczbą, to pole przyjmuje tylko liczby' SilverStripe\Forms\TimeField: VALIDATEFORMAT: 'Proszę wprowadź prawidłowy format czasu ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: 'Obiekty danych' + PLURALS: + one: 'Obiekt danych' + few: 'Obiektów danych' + many: 'Obiektów danych' + other: 'Obiektów danych {count}' + SINGULARNAME: 'Obiekt danych' SilverStripe\ORM\FieldType\DBBoolean: ANY: Jakikolwiek + NOANSWER: Nie + YESANSWER: Tak SilverStripe\ORM\FieldType\DBDate: + DAYS_SHORT_PLURALS: + one: '{count} dzień' + few: '{count} dni' + many: '{count} dni' + other: '{count} dni' + HOURS_SHORT_PLURALS: + one: '{count} godzina' + few: '{count} godzin' + many: '{count} godzin' + other: '{count} godzin' LessThanMinuteAgo: 'mniej niż minuta' + MINUTES_SHORT_PLURALS: + one: '{count} minuta' + few: '{count} minut' + many: '{count} minut' + other: '{count} minut' + MONTHS_SHORT_PLURALS: + one: '{count} miesiąc' + few: '{count} miesięcy' + many: '{count} miesięcy' + other: '{count} miesięcy' + SECONDS_SHORT_PLURALS: + one: '{count} sekunda' + few: '{count} sekund' + many: '{count} sekund' + other: '{count} sekund' TIMEDIFFAGO: '{difference} temu' TIMEDIFFIN: 'w {difference}' + YEARS_SHORT_PLURALS: + one: '{count} rok' + few: '{count} lat' + many: '{count} lat' + other: '{count} lat' SilverStripe\ORM\FieldType\DBEnum: ANY: Jakikolwiek + SilverStripe\ORM\Hierarchy: + LIMITED_TITLE: 'Zbyt wiele dzieci ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: InfiniteLoopNotAllowed: 'Znaleziono nieskończoną pętlę wewnątrz hierarchii "{type}". Proszę zmień rodzica by to rozwiązać.' + LIMITED_TITLE: 'Zbyt wiele dzieci ({count})' + SilverStripe\ORM\ValidationException: + DEFAULT_ERROR: 'Niepoprawne dane' SilverStripe\Security\BasicAuth: ENTERINFO: 'Wprowadź username i hasło' ERRORNOTADMIN: 'Ten użytkownik nie jest administratorem' ERRORNOTREC: 'Nie istnieje taki username/hasło' + SilverStripe\Security\CMSMemberLoginForm: + PASSWORDEXPIRED: '

Twoje hasło wygasło. Prosimy wybrać nowe.

' + SilverStripe\Security\CMSSecurity: + INVALIDUSER: '

Niepoprawny użytkownik. Prosimy o ponownie uwierzytelnienie – aby kontynuować.

' + LOGIN_MESSAGE: '

Twoja sesja wygasła z powodu braku aktywności

' + LOGIN_TITLE: 'Wróć do strony, z którym połączenie zostało przerwane, logując się ponownie' + SUCCESS: Sukces + SUCCESSCONTENT: '

Zalogowano poprawnie! Jeżeli nie zostaniesz automatycznie przekierowany kliknij tutaj

' + SUCCESS_TITLE: 'Zalogowano poprawne' + SilverStripe\Security\DefaultAdminService: + DefaultAdminFirstname: 'Domyślny administrator' SilverStripe\Security\Group: AddRole: 'Dodaj rolę dla tej grupy' Code: 'Kod Grupy' DefaultGroupTitleAdministrators: Administratorzy DefaultGroupTitleContentAuthors: 'Autor treści' Description: Opis + GROUPNAME: 'Nazwa Grupy' GroupReminder: 'Jeśli wybierzesz nadrzędną grupę, obecna grupa otrzyma wszystkie jej role' HierarchyPermsError: 'Nie można przyporządkować uprzywilejowanej grupy "{group}" (wymagane uprawnienie ADMIN)' Locked: 'Zablokowana?' + MEMBERS: Użytkownicy + NEWGROUP: 'Nowa grupa' NoRoles: 'Nie znaleziono ról' + PERMISSIONS: Uprawnienia + PLURALNAME: Grupy + PLURALS: + one: Grupa + few: Grup + many: Grup + other: '{count} grup' Parent: 'Grupa nadrzędna' + ROLES: Role + ROLESDESCRIPTION: 'Role są wstępnie zdefiniowanymi zestawami uprawnień i można je przypisać do grup.
TW razie potrzeby są one dziedziczone z grup nadrzędnych.' RolesAddEditLink: 'Zarządzaj rolami' + SINGULARNAME: Grupa Sort: 'Kolejność Sortowania' has_many_Permissions: Zezwolenia many_many_Members: Użytkownicy SilverStripe\Security\LoginAttempt: + Email: 'Adres e-mail' + EmailHashed: 'Adres e-mail (hashed)' IP: 'Adres IP' + PLURALNAME: 'Próby logowania' + PLURALS: + one: 'Próba logowania' + few: 'Prób logowania' + many: 'Próby logowania {count}' + other: 'Próby logowania {count}' + SINGULARNAME: 'Próba logowania' Status: Status SilverStripe\Security\Member: ADDGROUP: 'Dodaj grupę' BUTTONCHANGEPASSWORD: 'Zmień hasło' BUTTONLOGIN: Zaloguj BUTTONLOGINOTHER: 'Zaloguj jako ktoś inny' + BUTTONLOGOUT: 'Wyloguj się' BUTTONLOSTPASSWORD: 'Zgubiłem hasło' CONFIRMNEWPASSWORD: 'Potwierdź nowe hasło' CONFIRMPASSWORD: 'Potwierdź hasło' + CURRENT_PASSWORD: 'Aktualne hasło' + EDIT_PASSWORD: 'Nowe hasło' EMAIL: E-mail EMPTYNEWPASSWORD: 'Nowe hasło nie może być puste, spróbuj ponownie.' ENTEREMAIL: 'Wpisz adres e-mail aby otrzymać link do zmiany hasła.' @@ -108,12 +243,23 @@ pl: ERRORWRONGCRED: 'Podane dane są niepoprawne. Proszę spróbować ponownie.' FIRSTNAME: Imię INTERFACELANG: 'Język interfejsu' + KEEPMESIGNEDIN: 'Zapamiętaj mnie' LOGGEDINAS: 'Zostałeś zalogowany jako {name}.' NEWPASSWORD: 'Nowe hasło' PASSWORD: Hasło + PASSWORDEXPIRED: 'Twoje hasło wygasło. Prosimy ustawić nowe.' + PLURALNAME: Użytkownicy + PLURALS: + one: Użytkownik + few: '{count} użytkowników' + many: '{count} użytkowników' + other: '{count} użytkowników' + REMEMBERME: 'Pamiętaj mnie następnym razem? (przez {count} dni na tym urządzeniu)' + SINGULARNAME: Użytkownik SUBJECTPASSWORDCHANGED: 'Twoje hasło zostało zmienione' SUBJECTPASSWORDRESET: 'Twój link do zmiany hasła' SURNAME: Nazwisko + VALIDATIONADMINLOSTACCESS: 'Nie można usunąć wszystkich grup administracyjnych z Twojego profilu' ValidationIdentifierFailed: 'Nie można nadpisać istniejącego użytkownika #{id} o identycznym identyfikatorze ({name} = {value})' WELCOMEBACK: 'Witaj ponownie, {firstname}' YOUROLDPASSWORD: 'Twoje stare hasło' @@ -122,15 +268,42 @@ pl: db_LockedOutUntil: 'Zablokowany do' db_Password: Hasło db_PasswordExpiry: 'Data wygaśnięcia hasła' + SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: + AUTHENTICATORNAME: 'Formularz logowania użytkownika CMS' + BUTTONFORGOTPASSWORD: 'Zapomniałeś hasła?' + BUTTONLOGIN: 'Zaloguj mnie spowrotem' + BUTTONLOGOUT: 'Wyloguj się' + SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: + ERRORWRONGCRED: 'Podane dane są niepoprawne. Proszę spróbować ponownie.' + NoPassword: 'Hasło nie zostało skonfigurowane dla tego użytkownika.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'E-mail i hasło' + SilverStripe\Security\MemberPassword: + PLURALNAME: 'Hasła użytkownika' + PLURALS: + one: 'Hasło użytkownika' + few: 'Haseł użytkownika' + many: 'Haseł użytkownika' + other: '{count} haseł użytkownika ' + SINGULARNAME: 'Hasło użytkownika' SilverStripe\Security\PasswordValidator: LOWCHARSTRENGTH: 'Proszę zwiększyć siłę hasła, dodając niektóre z następujących znaków: % s' PREVPASSWORD: 'Użyłeś już tego hasła wcześniej, proszę wybrać nowe' TOOSHORT: 'Hasło jest za krótkie, proszę podać {minimum} znaków lub więcej' SilverStripe\Security\Permission: AdminGroup: Administrator + CMS_ACCESS_CATEGORY: 'Dostęp do CMS''a' CONTENT_CATEGORY: 'Uprawnienie edycji treści' FULLADMINRIGHTS: 'Pełne prawa administracyjne' FULLADMINRIGHTS_HELP: 'Zatwierdza i nadpisuje wszystkie istniejące uprawnienia' + PERMISSIONS_CATEGORY: 'Uprawnienia ról i dostępu' + PLURALNAME: Uprawnienia + PLURALS: + one: Uprawnienie + few: Uprawnień + many: Uprawnień + other: '{count} uprawnień' + SINGULARNAME: Uprawnienie UserPermissionsIntro: 'Przydzielenie grup temu użytkownikowi spowoduje zmianę jego uprawnień. Odwołaj się do sekcji Grupy aby dowiedzieć się więcej o uprawnieniach grupowych.' SilverStripe\Security\PermissionCheckboxSetField: AssignedTo: 'przypisany do "{title}"' @@ -139,20 +312,41 @@ pl: FromRoleOnGroup: 'odziedziczone z roli "{roletitle}" w grupie "{grouptitle}"' SilverStripe\Security\PermissionRole: OnlyAdminCanApply: 'Tylko administrator może to zastosować' + PLURALNAME: Role + PLURALS: + one: Rola + few: ról + many: ról + other: '{count} ról' + SINGULARNAME: Rola Title: Tytuł SilverStripe\Security\PermissionRoleCode: + PLURALNAME: 'Kod roli uprawnienia' + PLURALS: + one: 'Kod roli uprawnienia' + few: 'Kodów ról uprawnień' + many: 'Kodów ról uprawnień' + other: '{count} kodów ról uprawnień' PermsError: 'Nie można przyporządkować uprzywilejowanego uprawnienia "{code}" (wymagane uprawnienie ADMIN)' + SINGULARNAME: 'Kod roli uprawnienia' + SilverStripe\Security\RememberLoginHash: + PLURALNAME: 'Hasła logowania' + PLURALS: + one: 'Hasło logowania' + few: 'Haseł logowania' + many: 'Haseł logowania' + other: '{count} haseł logowania' + SINGULARNAME: 'Hasło logowania' SilverStripe\Security\Security: ALREADYLOGGEDIN: 'Nie masz dostępu do tej strony. Jeśli posiadasz inne konto, które umożliwi Ci dostęp do tej strony, możesz się zalogować poniżej' BUTTONSEND: 'Wyślij mi link do zresetowania hasła' CHANGEPASSWORDBELOW: 'Możesz zmienić swoje hasło poniżej' CHANGEPASSWORDHEADER: 'Zmień swoje hasło' + CONFIRMLOGOUT: 'Kliknij przycisk poniżej, aby potwierdzić, że chcesz się wylogować.' ENTERNEWPASSWORD: 'Proszę wprowadż nowe hasło' ERRORPASSWORDPERMISSION: 'Musisz być zalogowany aby zmienić hasło' LOGIN: Logowanie + LOGOUT: 'Wyloguj się' LOSTPASSWORDHEADER: 'Nie pamiętam hasła' NOTEPAGESECURED: 'Ta strona jest zabezpieczona. Wpisz swoje dane a my wyślemy Ci potwierdzenie niebawem' - NOTERESETLINKINVALID: '

Link resetujący hasło wygasł lub jest nieprawidłowy.

Możesz poprosić o nowy tutaj lub zmień swoje hasło po zalogowaniu się.

' NOTERESETPASSWORD: 'Wpisz adres e-mail, na który mamy wysłać link gdzie możesz zresetować swoje hasło' - PASSWORDSENTHEADER: 'Link resetujący hasła został wysłany do ''{email}''' - PASSWORDSENTTEXT: 'Dziękujemy! Link resetujący hasło został wysłany do ''{email}'', o ile konto użytkownika dla takiego e-maila istnieje.' diff --git a/lang/ru.yml b/lang/ru.yml index 73602e013..add72be7f 100644 --- a/lang/ru.yml +++ b/lang/ru.yml @@ -339,7 +339,4 @@ ru: LOGOUT: Выйти LOSTPASSWORDHEADER: 'Восстановление пароля' NOTEPAGESECURED: 'Эта страница защищена. Пожалуйста, введите свои учетные данные для входа.' - NOTERESETLINKINVALID: '

Неверная ссылка переустановки пароля или время действия ссылки истекло.

Вы можете повторно запросить ссылку, щелкнув здесь, или поменять пароль, войдя в систему.

' NOTERESETPASSWORD: 'Введите Ваш адрес email, и Вам будет отправлена ссылка, по которой Вы сможете переустановить свой пароль' - PASSWORDSENTHEADER: 'Ссылка для переустановки пароля выслана на ''{email}''' - PASSWORDSENTTEXT: 'Ссылка переустановки пароля была выслана на адрес ''{email}'' (письмо дойдет до получателя только в том случае, если аккаунт с таким электронным адресом действительно зарегистрирован).' diff --git a/lang/sk.yml b/lang/sk.yml index 861045fc6..88f4bf260 100644 --- a/lang/sk.yml +++ b/lang/sk.yml @@ -228,7 +228,4 @@ sk: LOGIN: Prihlásiť LOSTPASSWORDHEADER: 'Zabudnuté heslo' NOTEPAGESECURED: 'Táto stránka je zabezpečená. Zadajte svoje prihlasovacie údaje a my Vám zároveň pošleme práva.' - NOTERESETLINKINVALID: '

Odkaz na resetovanie hesla nie je platný alebo je vypršala jeho platnosť.

Môžete požiadať o nový tu alebo zmeňte svoje heslo po prihlásení.

' NOTERESETPASSWORD: 'Zadajte svoju e-mailovú adresu a my Vám pošleme odkaz na resetovanie hesla' - PASSWORDSENTHEADER: 'Odkaz na resetovanie hesla bol odoslaný na ''{email}''' - PASSWORDSENTTEXT: 'Ďakujeme! Resetovací odkaz bol odoslaný na ''''{email}'''', pokiaľ účet existuje pre túto emailovú adresu.' diff --git a/lang/sl.yml b/lang/sl.yml index bccd51826..5496aff5f 100644 --- a/lang/sl.yml +++ b/lang/sl.yml @@ -135,7 +135,4 @@ sl: LOGIN: Prijava LOSTPASSWORDHEADER: 'Izgubljeno geslo' NOTEPAGESECURED: 'Stran je zaščitena. Da bi lahko nadaljevali, vpišite svoje podatke.' - NOTERESETLINKINVALID: '

Povezava za ponastavitev gesla je napačna ali pa je njena veljavnost potekla.

Tukaj lahko zaprosite za novo povezavo or pa zamenjate geslo, ko se prijavite v sistem.

' NOTERESETPASSWORD: 'Vpišite e-naslov, na katerega vam bomo poslali povezavo za ponastavitev gesla' - PASSWORDSENTHEADER: 'Povezava za ponastavitev gesla je bila poslana na e-naslov ''{email}''.' - PASSWORDSENTTEXT: 'Hvala! Povezava za ponastavitev gesla je bila poslana na e-naslov ''{email}'', ki je naveden kot e-naslov vašega računa. ' diff --git a/lang/sr.yml b/lang/sr.yml index 07f642278..622b657b3 100644 --- a/lang/sr.yml +++ b/lang/sr.yml @@ -151,7 +151,4 @@ sr: ERRORPASSWORDPERMISSION: 'Морате да будете пријављени да бисте променили своју лозинку!' LOGIN: Пријављивање NOTEPAGESECURED: 'Ова страна је обезбеђена. Унесите своје податке и ми ћемо вам послати садржај.' - NOTERESETLINKINVALID: '

Линк за ресетовање лозинке је погрешан или је истекло време за његово коришћење.

Можете да захтевате нови овде или да промените Вашу лозинку након што се пријавите.

' NOTERESETPASSWORD: 'Унесите своју адресу е-поште и ми ћемо вам послати линк помоћу којег можете да промените своју лозинку' - PASSWORDSENTHEADER: 'Линк за ресетовање лозинке послат је на адресу е-поште: ''{email}''' - PASSWORDSENTTEXT: 'Хвала Вам! Линк за ресетовање лозинке је послат не адресу е-поште ''{email}''. Порука ће стићи примаоцу само ако постоји регистрован налог са том адресом е-поште.' diff --git a/lang/sr@latin.yml b/lang/sr@latin.yml index 1b210ae51..f91aa9337 100644 --- a/lang/sr@latin.yml +++ b/lang/sr@latin.yml @@ -150,7 +150,4 @@ sr@latin: ERRORPASSWORDPERMISSION: 'Morate da budete prijavljeni da biste promenili svoju lozinku!' LOGIN: Prijavljivanje NOTEPAGESECURED: 'Ova strana je obezbeđena. Unesite svoje podatke i mi ćemo vam poslati sadržaj.' - NOTERESETLINKINVALID: '

Link za resetovanje lozinke je pogrešan ili je isteklo vreme za njegovo korišćenje.

Možete da zahtevate novi ovde ili da promenite Vašu lozinku nakon što se prijavite.

' NOTERESETPASSWORD: 'Unesite svoju adresu e-pošte i mi ćemo vam poslati link pomoću kojeg možete da promenite svoju lozinku' - PASSWORDSENTHEADER: 'Link za resetovanje lozinke poslat je na adresu e-pošte: ''{email}''' - PASSWORDSENTTEXT: 'Hvala Vam! Link za resetovanje lozinke je poslat ne adresu e-pošte ''{email}''. Poruka će stići primaocu samo ako postoji registrovan nalog sa tom adresom e-pošte.' diff --git a/lang/sr_RS.yml b/lang/sr_RS.yml index fc79812da..298049430 100644 --- a/lang/sr_RS.yml +++ b/lang/sr_RS.yml @@ -150,7 +150,4 @@ sr_RS: ERRORPASSWORDPERMISSION: 'Морате да будете пријављени да бисте променили своју лозинку!' LOGIN: Пријављивање NOTEPAGESECURED: 'Ова страна је обезбеђена. Унесите своје податке и ми ћемо вам послати садржај.' - NOTERESETLINKINVALID: '

Линк за ресетовање лозинке је погрешан или је истекло време за његово коришћење.

Можете да захтевате нови овде или да промените Вашу лозинку након што се пријавите.

' NOTERESETPASSWORD: 'Унесите своју адресу е-поште и ми ћемо вам послати линк помоћу којег можете да промените своју лозинку' - PASSWORDSENTHEADER: 'Линк за ресетовање лозинке послат је на адресу е-поште: ''{email}''' - PASSWORDSENTTEXT: 'Хвала Вам! Линк за ресетовање лозинке је послат не адресу е-поште ''{email}''. Порука ће стићи примаоцу само ако постоји регистрован налог са том адресом е-поште.' diff --git a/lang/sr_RS@latin.yml b/lang/sr_RS@latin.yml index f39b36058..453ffa17d 100644 --- a/lang/sr_RS@latin.yml +++ b/lang/sr_RS@latin.yml @@ -151,7 +151,4 @@ sr_RS@latin: ERRORPASSWORDPERMISSION: 'Morate da budete prijavljeni da biste promenili svoju lozinku!' LOGIN: Prijavljivanje NOTEPAGESECURED: 'Ova strana je obezbeđena. Unesite svoje podatke i mi ćemo vam poslati sadržaj.' - NOTERESETLINKINVALID: '

Link za resetovanje lozinke je pogrešan ili je isteklo vreme za njegovo korišćenje.

Možete da zahtevate novi ovde ili da promenite Vašu lozinku nakon što se prijavite.

' NOTERESETPASSWORD: 'Unesite svoju adresu e-pošte i mi ćemo vam poslati link pomoću kojeg možete da promenite svoju lozinku' - PASSWORDSENTHEADER: 'Link za resetovanje lozinke poslat je na adresu e-pošte: ''{email}''' - PASSWORDSENTTEXT: 'Hvala Vam! Link za resetovanje lozinke je poslat ne adresu e-pošte ''{email}''. Poruka će stići primaocu samo ako postoji registrovan nalog sa tom adresom e-pošte.' diff --git a/lang/sv.yml b/lang/sv.yml index f35c2ee99..f2a18d659 100644 --- a/lang/sv.yml +++ b/lang/sv.yml @@ -93,7 +93,12 @@ sv: DeletePermissionsFailure: 'Rättighet för att radera saknas' Deleted: 'Raderade {type} {name}' Save: Spara + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Ändra + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Du kan inte radera dig själv från den här gruppen, då du då kommer att förlora dina admin-rättigheter' SilverStripe\Forms\GridField\GridFieldPaginator: + OF: av Page: Sida View: Visa SilverStripe\Forms\MoneyField: @@ -108,6 +113,12 @@ sv: VALIDATION: '''{value}'' är inget nummer, bara siffror (utan mellanslag) kan accepteras för det här fältet' SilverStripe\Forms\TimeField: VALIDATEFORMAT: 'Var god att ange tid i ett giltigt format ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: Dataobjekt + PLURALS: + one: 'Ett dataobjekt' + other: '{count} Dataobjekt' + SINGULARNAME: Dataobjekt SilverStripe\ORM\FieldType\DBBoolean: ANY: 'Vilken som helst' NOANSWER: Nej @@ -136,6 +147,8 @@ sv: other: '{count} år' SilverStripe\ORM\FieldType\DBEnum: ANY: 'Vilken som helst' + SilverStripe\ORM\FieldType\DBForeignKey: + DROPDOWN_THRESHOLD_FALLBACK_MESSAGE: 'För många relaterade objekt; använder fallback-fält' SilverStripe\ORM\Hierarchy: LIMITED_TITLE: 'För många barn ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: @@ -221,6 +234,7 @@ sv: PLURALS: one: 'En medlem' other: '{count} medlemmar' + REMEMBERME: 'Kom ihåg mig nästa gång? (i {count} dagar på denna enhet)' SINGULARNAME: Medlem SUBJECTPASSWORDCHANGED: 'Ditt lösenord har ändrats' SUBJECTPASSWORDRESET: 'Din återställningslänk' @@ -288,7 +302,6 @@ sv: LOGOUT: 'Logga ut' LOSTPASSWORDHEADER: 'Bortglömt lösenord' NOTEPAGESECURED: 'Den här sidan är låst. Fyll i dina uppgifter nedan så skickar vi dig vidare.' - NOTERESETLINKINVALID: '

Återställningslänk för lösenord är felaktig eller för gammal.

Du kan begära en ny här eller ändra ditt lösenord när du loggat in.

' NOTERESETPASSWORD: 'Ange din e-postadress så skickar vi en länk med vilken du kan återställa ditt lösenord' - PASSWORDSENTHEADER: 'Återställningslänk för lösenord har skickats till ''{email}''' - PASSWORDSENTTEXT: 'Tack en återställningslänk har skickats till ''{email}'', förutsatt att ett konto med den addressen finns.' + PASSWORDRESETSENTHEADER: 'Återställningslänk för lösenord skickad' + PASSWORDRESETSENTTEXT: 'Tack. En återställningslänk har skickats, förutsatt att ett konto med denna adress existerar.' diff --git a/lang/zh.yml b/lang/zh.yml index 26c8e2893..748ee671c 100644 --- a/lang/zh.yml +++ b/lang/zh.yml @@ -166,7 +166,4 @@ zh: LOGIN: 登录 LOSTPASSWORDHEADER: 忘记密码 NOTEPAGESECURED: 该页面受安全保护。请在下面输入您的证书,然后我们会立即将您引导至该页面。 - NOTERESETLINKINVALID: '

密码重设链接无效或已过期。

您可以在这里 要求一个新的或在登录后更改您的密码。

' NOTERESETPASSWORD: 请输入您的电子邮件地址,然后我们会将一个链接发送给您,您可以用它来重设您的密码 - PASSWORDSENTHEADER: '密码重设链接已发送至''{email}''' - PASSWORDSENTTEXT: '谢谢!复位链接已发送到 ''{email}'',假定此电子邮件地址存在一个帐户。' From 55674959f8a48237bf1fdee9ccac149301bd9619 Mon Sep 17 00:00:00 2001 From: Vagrant Default User Date: Wed, 7 Nov 2018 22:38:52 +1300 Subject: [PATCH 14/17] Added 4.1.3 changelog --- docs/en/04_Changelogs/4.1.3.md | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/en/04_Changelogs/4.1.3.md b/docs/en/04_Changelogs/4.1.3.md index 26ac3041c..c7b1ba1b4 100644 --- a/docs/en/04_Changelogs/4.1.3.md +++ b/docs/en/04_Changelogs/4.1.3.md @@ -10,3 +10,39 @@ behaviour to that of SilverStripe 3 where `Extension` instances are of lowest im default value. If you rely on your `Extension` or module providing an overriding config value, please move this to yaml. + +## Change Log + +### Security + + * 2018-11-06 [6cb1bf5](https://github.com/silverstripe/silverstripe-admin/commit/6cb1bf53a6fd5b54b6f7bbe7a1d7b939e176cf53) Add CSRF protection (Aaron Carlino) - See [ss-2018-007](https://www.silverstripe.org/download/security-releases/ss-2018-007) + * 2018-08-21 [af000be](https://github.com/silverstripe/silverstripe-framework/commit/af000bea9b16ea553cae7f7f662f74ab8dc343df) Add confirmation token to dev/build (Loz Calver) - See [ss-2018-019](https://www.silverstripe.org/download/security-releases/ss-2018-019) + * 2018-07-29 [5425195](https://github.com/silverstripe/silverstripe-framework/commit/54251952387394d72b221e797a80edfbf9a973ee) Ignore arguments in mysqli::real_connect backtrace calls (Robbie Averill) - See [ss-2018-018](https://www.silverstripe.org/download/security-releases/ss-2018-018) + +### Features and Enhancements + + * 2018-04-18 [fef734b](https://github.com/silverstripe/recipe-core/commit/fef734b5484d86f5afd4e857c556b8c1d8d66c16) Provide default IIS rewriting rules with recipe (Damian Mooyman) + +### Bugfixes + + * 2018-10-24 [e72fc9e](https://github.com/silverstripe/silverstripe-framework/commit/e72fc9e3d0f35a1d43f55f83f9919f67d72fb7cb) DataObject singleton creation (#8516) (Sam Minnée) + * 2018-09-18 [bbe7c66](https://github.com/silverstripe/silverstripe-asset-admin/commit/bbe7c660cf40d4c942eaf6e76755eeaf46c63471) Add `AssetAdmin::getMinimalistObjectFromData()` to build file metadata for UploadField (#829) (Maxime Rainville) + * 2018-09-13 [5c102de](https://github.com/silverstripe/silverstripe-cms/commit/5c102decbde43395e14aeff83a20c4c6f1d048ae) Improve performance of CMSMain::getArchiveWarningMessage (#2231) (Maxime Rainville) + * 2018-09-03 [1c4311d](https://github.com/silverstripe/silverstripe-asset-admin/commit/1c4311d4e6548600272daa0ce83afa12cf7e99c3) description for docs.silverstripe.org (wernerkrauss) + * 2018-09-03 [b922c0d](https://github.com/silverstripe/silverstripe-framework/commit/b922c0d7327b5d0222dd280afcb64f83a09ea859) Check scheme is truthy before setting it to the request (Robbie Averill) + * 2018-08-28 [d651d0f](https://github.com/silverstripe/silverstripe-framework/commit/d651d0fbfcababeaf317b27cb00b4f33b9d99eab) Use base class (not remapping target class) when looking up whether object is versioned (Robbie Averill) + * 2018-08-27 [4da5569](https://github.com/silverstripe/silverstripe-framework/commit/4da5569232505ee574e0b5106ff2116611393aa4) ensure createFromVariables takes correct params on CLIRequestBuilder (Scott Hutchinson) + * 2018-08-15 [0c713b5](https://github.com/silverstripe/silverstripe-assets/commit/0c713b5b1eb6a08ac00dcadb187b8b3ef7115fc4) Fix routing for files with dots in filename (Damian Mooyman) + * 2018-08-14 [27ac001](https://github.com/silverstripe/silverstripe-framework/commit/27ac001d5b27cce4f80ce4b3335c14708b116830) email rendering should not include requirements (Thomas Portelange) + * 2018-08-14 [8ec551e](https://github.com/silverstripe/silverstripe-cms/commit/8ec551e57b04d00d6897d06c2779557f0ec8109d) Broken "show as list" (#2232) (Maxime Rainville) + * 2018-07-26 [fea9ef7](https://github.com/silverstripe/silverstripe-admin/commit/fea9ef7d2a53904086f9fad6eedba7bb307c8578) #579 BUG Ambiguous column RecordID when doing batch actions (Ed Linklater) + * 2018-07-14 [a0e0bed](https://github.com/silverstripe/recipe-core/commit/a0e0bed7e7fe83b98264563efdeffa82d0d01d04) Use Injector to create PasswordValidators (Daniel Hensby) + * 2018-07-14 [8703839](https://github.com/silverstripe/silverstripe-framework/commit/8703839eb142ba0414f4d84f885ff898c39d6786) updateValidatePassword calls need to be masked from backtraces (Daniel Hensby) + * 2018-07-12 [e80c7e7](https://github.com/silverstripe/silverstripe-cms/commit/e80c7e712b916712d4ec7b6b8359ccf71dc9da04) Restore button now has warning colour and correct icon (Robbie Averill) + * 2018-07-12 [d122995](https://github.com/silverstripe/silverstripe-framework/commit/d1229956523d69f63c9e725b261c0142d5ee1de3) Duplicate config values for cascade_duplicates no longer duplicate their duplicates (Robbie Averill) + * 2018-06-19 [725212a](https://github.com/silverstripe/silverstripe-framework/commit/725212a707f6b724aff6548c3680b2cd66e9a6bb) Allow dispatcher in Embed to be configured with injector (#8192) (Robbie Averill) + * 2018-06-13 [932eb2b](https://github.com/silverstripe/silverstripe-cms/commit/932eb2b22dfe6c30473b1cf973661c28c5b9c635) Fix CMS components failing to register on other CMS sections (#2182) (Damian Mooyman) + * 2018-05-21 [bf5b578](https://github.com/silverstripe/silverstripe-admin/commit/bf5b5787685765c35c175c303f3f7ee719ac9453) Adding a min-width to flexbox-area-grow that allows flex blocks to shrink below their content width (Guy) + * 2018-05-18 [9531535](https://github.com/silverstripe/silverstripe-framework/commit/953153500d490f5b5abf7283c34242c3b22a855a) Polymorphic relationship class columns have obsolete class names remapped (Robbie Averill) + * 2018-05-08 [97a8f56](https://github.com/silverstripe/silverstripe-admin/commit/97a8f56c43ddb3c77a5bbc452755d44afb9a9472) Add missing focus styles for preview options (fixes silverstripe/silverstripe-framework #2101) (Loz Calver) + * 2018-03-29 [4acec33](https://github.com/silverstripe/silverstripe-framework/commit/4acec33562e4e1230092eee7d76c2b8061ffc914) Fixed bug in config merging priorities so that config values set by extensions are now least important instead of most important (Daniel Hensby) From 3f321f935a0b7faa3d4ef788b4f69425db979095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Werner=20M=2E=20Krau=C3=9F?= Date: Wed, 7 Nov 2018 17:01:36 +0100 Subject: [PATCH 15/17] Convert::memstring2bytes should return integer value bytes are by nature an integer fixes #8572 --- src/Core/Convert.php | 6 +++--- tests/php/Core/ConvertTest.php | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Core/Convert.php b/src/Core/Convert.php index 7c8717724..3e4158111 100644 --- a/src/Core/Convert.php +++ b/src/Core/Convert.php @@ -556,7 +556,7 @@ class Convert * Preserves integer values like "1024" or "-1" * * @param string $memString A memory limit string, such as "64M" - * @return float + * @return int */ public static function memstring2bytes($memString) { @@ -568,10 +568,10 @@ class Convert if ($unit) { // Find the position of the unit in the ordered string which is the power // of magnitude to multiply a kilobyte by - return round($size * pow(1024, stripos('bkmgtpezy', $unit[0]))); + return (int)round($size * pow(1024, stripos('bkmgtpezy', $unit[0]))); } - return round($size); + return (int)round($size); } /** diff --git a/tests/php/Core/ConvertTest.php b/tests/php/Core/ConvertTest.php index 679c611e7..d1c1139d3 100644 --- a/tests/php/Core/ConvertTest.php +++ b/tests/php/Core/ConvertTest.php @@ -2,12 +2,12 @@ namespace SilverStripe\Core\Tests; +use Exception; +use InvalidArgumentException; use SilverStripe\Core\Convert; use SilverStripe\Dev\SapphireTest; use SilverStripe\View\Parsers\URLSegmentFilter; use stdClass; -use Exception; -use InvalidArgumentException; /** * Test various functions on the {@link Convert} class. @@ -576,15 +576,15 @@ XML public function memString2BytesProvider() { return [ - ['-1', (float)-1], - ['2048', (float)(2 * 1024)], - ['2k', (float)(2 * 1024)], - ['512M', (float)(512 * 1024 * 1024)], - ['512MiB', (float)(512 * 1024 * 1024)], - ['512 mbytes', (float)(512 * 1024 * 1024)], - ['512 megabytes', (float)(512 * 1024 * 1024)], - ['1024g', (float)(1024 * 1024 * 1024 * 1024)], - ['1024G', (float)(1024 * 1024 * 1024 * 1024)] + 'infinite' => ['-1', -1], + 'integer' => ['2048', 2 * 1024], + 'kilo' => ['2k', 2 * 1024], + 'mega' => ['512M', 512 * 1024 * 1024], + 'MiB' => ['512MiB', 512 * 1024 * 1024], + 'mbytes' => ['512 mbytes', 512 * 1024 * 1024], + 'megabytes' => ['512 megabytes', 512 * 1024 * 1024], + 'giga' => ['1024g', 1024 * 1024 * 1024 * 1024], + 'G' => ['1024G', 1024 * 1024 * 1024 * 1024] ]; } @@ -607,11 +607,11 @@ XML { return [ [200, '200B'], - [(2 * 1024), '2K'], - [(512 * 1024 * 1024), '512M'], - [(512 * 1024 * 1024 * 1024), '512G'], - [(512 * 1024 * 1024 * 1024 * 1024), '512T'], - [(512 * 1024 * 1024 * 1024 * 1024 * 1024), '512P'] + [2 * 1024, '2K'], + [512 * 1024 * 1024, '512M'], + [512 * 1024 * 1024 * 1024, '512G'], + [512 * 1024 * 1024 * 1024 * 1024, '512T'], + [512 * 1024 * 1024 * 1024 * 1024 * 1024, '512P'] ]; } } From 1db568cdb6bf7f6d0438b83b95d76f77999fc0f2 Mon Sep 17 00:00:00 2001 From: Aaron Carlino Date: Thu, 8 Nov 2018 16:25:41 +1300 Subject: [PATCH 16/17] Update translations --- lang/af.yml | 3 - lang/ar.yml | 8 -- lang/az.yml | 3 - lang/bg.yml | 8 -- lang/bs.yml | 3 - lang/ca.yml | 3 - lang/cs.yml | 8 -- lang/da.yml | 319 ++++++++++++++++++++++++++++++++++++++++++- lang/de.yml | 8 -- lang/de_DE.yml | 159 +++++++++++++++++++++ lang/en.yml | 2 - lang/eo.yml | 19 +-- lang/es.yml | 8 -- lang/es_AR.yml | 3 - lang/es_MX.yml | 2 - lang/et_EE.yml | 8 -- lang/fa_IR.yml | 6 - lang/fi.yml | 20 +-- lang/fo.yml | 3 - lang/fr.yml | 20 +-- lang/gl_ES.yml | 2 - lang/hr.yml | 5 - lang/id.yml | 8 -- lang/id_ID.yml | 8 -- lang/is.yml | 3 - lang/it.yml | 23 +--- lang/ja.yml | 8 -- lang/lt.yml | 8 -- lang/lv.yml | 3 - lang/mi.yml | 8 -- lang/nb.yml | 8 -- lang/nl.yml | 152 +++++++++++++++++++-- lang/pl.yml | 207 ++++++++++++++++++++++++++-- lang/pt.yml | 3 - lang/pt_BR.yml | 3 - lang/ro.yml | 2 - lang/ru.yml | 8 -- lang/sk.yml | 10 -- lang/sl.yml | 8 -- lang/sl_SI.yml | 5 - lang/sr.yml | 8 -- lang/sr@latin.yml | 8 -- lang/sr_RS.yml | 8 -- lang/sr_RS@latin.yml | 8 -- lang/sv.yml | 137 +++++++++++++++++-- lang/th.yml | 4 - lang/tr.yml | 3 - lang/uk.yml | 3 - lang/zh.yml | 8 -- 49 files changed, 962 insertions(+), 320 deletions(-) create mode 100644 lang/de_DE.yml diff --git a/lang/af.yml b/lang/af.yml index ddf2abee0..bbaf0c9cb 100644 --- a/lang/af.yml +++ b/lang/af.yml @@ -4,8 +4,6 @@ af: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: R SilverStripe\Forms\DateField: - NOTSET: 'Nie gestel nie' - TODAY: vandag VALIDDATEFORMAT2: 'Sleutel asseblief ''n geldige datum formaat in ({format})' VALIDDATEMAXDATE: 'Jou datum moet gelykstaande of ouer wees as die maksimum toelaatbare datum ({date})' VALIDDATEMINDATE: 'Jou datum moet net so out of nuwer wees as die minimum toelaatbare datum ({date})' @@ -36,7 +34,6 @@ af: RelationSearch: 'Soek vir verwantskap' ResetFilter: Herstel SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Verwyder Delete: Verwyder DeletePermissionsFailure: 'Geen toestemming om te verwyder nie' UnlinkRelation: Ontkoppel diff --git a/lang/ar.yml b/lang/ar.yml index ef2f216cf..518bf1344 100644 --- a/lang/ar.yml +++ b/lang/ar.yml @@ -5,8 +5,6 @@ ar: MAXIMUM: 'يجب أن تكون كلمات المرور على الأكثر {الحد الأقصى} حرفاً.' SHOWONCLICKTITLE: 'تغيير كلمة المرور' SilverStripe\Forms\DateField: - NOTSET: 'غير محدد' - TODAY: اليوم VALIDDATEFORMAT2: 'الرجاء إدخال صيغة تاريخ صحيحة ({صيغة})' VALIDDATEMAXDATE: 'التسجيل الخاص بك قد يكون أقدم أو مطابق لأقصى تاريخ مسموح به ({تاريخ})' VALIDDATEMINDATE: 'التسجيل الخاص بك قد يكون أحدث أو مطابق للحد الأدنى للتاريخ المسموح به ({تاريخ})' @@ -39,7 +37,6 @@ ar: RelationSearch: 'ابحث عن علاقة' ResetFilter: 'إعادة تعيين' SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: حذف Delete: حذف DeletePermissionsFailure: 'لا يوجد أية تصريحات حذف' EditPermissionsFailure: 'لا يوجد تصريح لإلغاء الربط بين السجلات' @@ -51,8 +48,6 @@ ar: DeletePermissionsFailure: 'لا يوجد تصريحات بالحذف' Deleted: '{type} {name} تم حذفه' Save: حفظ - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: تعديل SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: الكمية FIELDLABELCURRENCY: العملة @@ -155,7 +150,4 @@ ar: LOGIN: دخول LOSTPASSWORDHEADER: 'كلمة مرور مفقودة' NOTEPAGESECURED: 'هذه الصفحة محمية بكلمة مرور ، أدخل بيانات دخولك بالأسفل ليتم السماح لك بالوصول للصفحة' - NOTERESETLINKINVALID: "

رابط إعادة تعيين كلمة المرور غير صحيح أو نفذت صلاحيته.

\n

\nيمكنك طلب رابط جديد <\"{a href=\"{link1\"> هنا \n أو تغيير كلمة المرور الخاصة بك بعد <\"{a href=\"{link2\"> تسجيل دخولك.\n

" NOTERESETPASSWORD: 'أدخل بريدك الإلكتروني و سيتم إرسال رابط إعادة تهيئة كلمة المرور ' - PASSWORDSENTHEADER: 'رابط استعادة كلمة المرور تم إرساله إلى ''{بريدك}''' - PASSWORDSENTTEXT: 'شكرا لك! تم إرسال رابط إعادة تعيين إلى ''{بريدك}''، بشرط وجود حساب قائم بالنسبة لعنوان هذا البريد الإلكتروني .' diff --git a/lang/az.yml b/lang/az.yml index 392264a1b..7629d5d3b 100644 --- a/lang/az.yml +++ b/lang/az.yml @@ -1,9 +1,6 @@ az: SilverStripe\Forms\ConfirmedPasswordField: SHOWONCLICKTITLE: 'Parolu dəyiş' - SilverStripe\Forms\DateField: - NOTSET: 'təyin edilməyib' - TODAY: 'bu gün' SilverStripe\Forms\DropdownField: CHOOSE: (Seçin) SilverStripe\Forms\Form: diff --git a/lang/bg.yml b/lang/bg.yml index 91c831c04..241841f1e 100644 --- a/lang/bg.yml +++ b/lang/bg.yml @@ -37,8 +37,6 @@ bg: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'не е зададена' - TODAY: днес VALIDDATEFORMAT2: 'Моля, въведете валиден формат за дата ({format})' VALIDDATEMAXDATE: 'Датата трябва да бъде същата или преди ({date})' VALIDDATEMINDATE: 'Датата трябва да бъде същата или след ({date})' @@ -86,7 +84,6 @@ bg: RelationSearch: 'Търсене на връзка' ResetFilter: Изчистване SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Изтриване Delete: Изтрий DeletePermissionsFailure: 'Изтриването не е разрешено' EditPermissionsFailure: 'Нямате права за премахване на връзката' @@ -98,8 +95,6 @@ bg: DeletePermissionsFailure: 'Изтриването не е разрешено' Deleted: 'Изтрити {type} {name}' Save: Запис - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Редактиране SilverStripe\Forms\GridField\GridFieldPaginator: OF: от Page: Страница @@ -318,7 +313,4 @@ bg: LOGOUT: Изход LOSTPASSWORDHEADER: 'Забравена парола' NOTEPAGESECURED: 'Тази страница е защитена. Въведете вашите данни по-долу, за да продължите.' - NOTERESETLINKINVALID: '

Връзката за нулиране на парола не е вярна или е просрочена.

Можете да заявите нова тук или да промените паролата си след като влезете.

' NOTERESETPASSWORD: 'Въведете вашият email адрес и ще ви изпратим линк, с който ще можете да смените паролата си' - PASSWORDSENTHEADER: 'Връзка за нулиране на парола беше изпратена на ''{email}''' - PASSWORDSENTTEXT: 'Благодарим ви! Връзка за нулиране на паролата беше изпратен на ''{email}'', ако съществува акаунт с този имейл адрес.' diff --git a/lang/bs.yml b/lang/bs.yml index eca1e7246..3a2ac1a35 100644 --- a/lang/bs.yml +++ b/lang/bs.yml @@ -4,9 +4,6 @@ bs: YESANSWER: Da SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: KM - SilverStripe\Forms\DateField: - NOTSET: 'nije postavljeno' - TODAY: danas SilverStripe\Forms\DropdownField: CHOOSE: (Izaberite) SilverStripe\Forms\Form: diff --git a/lang/ca.yml b/lang/ca.yml index b93a85cc0..4ffdc98fe 100644 --- a/lang/ca.yml +++ b/lang/ca.yml @@ -3,9 +3,6 @@ ca: SHOWONCLICKTITLE: 'Canvia la contrasenya' SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: €E - SilverStripe\Forms\DateField: - NOTSET: 'no definit' - TODAY: avui SilverStripe\Forms\DropdownField: CHOOSE: (Trieu) SilverStripe\Forms\Form: diff --git a/lang/cs.yml b/lang/cs.yml index 9e7bf5d6a..759f0268e 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -13,8 +13,6 @@ cs: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: Kč SilverStripe\Forms\DateField: - NOTSET: nenastaveno - TODAY: dnes VALIDDATEFORMAT2: 'Prosím zadejte platný formát datumu ({format})' VALIDDATEMAXDATE: 'Váš datum musí být starší nebo odpovídající maximu povoleného datumu ({date})' VALIDDATEMINDATE: 'Váš datum musí být novější nebo odpovídající minimu povoleného datumu ({date})' @@ -51,7 +49,6 @@ cs: RelationSearch: 'Vztah hledání' ResetFilter: Resetovat SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Smazat Delete: Smazat DeletePermissionsFailure: 'Žádná oprávnění mazat' EditPermissionsFailure: 'Žádné oprávnění pro rozpojení záznamu' @@ -63,8 +60,6 @@ cs: DeletePermissionsFailure: 'Žádná oprávnění mazat' Deleted: 'Smazáno {type} {name}' Save: Uložit - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Editovat SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Částka FIELDLABELCURRENCY: Měna @@ -199,7 +194,4 @@ cs: LOGIN: Přihlásit LOSTPASSWORDHEADER: 'Zapomenuté heslo' NOTEPAGESECURED: 'Tato stránka je zabezpečená. Vložte své přihlašovací údaje a my Vám zároveň pošleme práva.' - NOTERESETLINKINVALID: '

Odkaz na resetování hesla není platný nebo je prošlý.

Můžete požádat o nový zde nebo změňte své heslo až se přihlásíte.

' NOTERESETPASSWORD: 'Zadejte svou e-mailovou adresu a bude vám zaslán nulovací odkaz pro Vaše heslo' - PASSWORDSENTHEADER: 'Odkaz na resetování hesla byl odeslán na ''{email}''' - PASSWORDSENTTEXT: 'Děkujeme! Resetovací odkaz byl odeslán na ''{email}'', pokud účet existuje pro tuto emailovou adresu.' diff --git a/lang/da.yml b/lang/da.yml index 8dc512b23..e203c1876 100644 --- a/lang/da.yml +++ b/lang/da.yml @@ -1,5 +1,322 @@ da: + SilverStripe\Admin\LeftAndMain: + VersionUnknown: ukendt + SilverStripe\AssetAdmin\Forms\UploadField: + Dimensions: Dimensioner + EDIT: Rediger + EDITINFO: 'Rediger denne fil' + REMOVE: Fjern + SilverStripe\Control\ChangePasswordEmail_ss: + CHANGEPASSWORDFOREMAIL: 'Koden for kontoen med email addressen {email} er ændret. Hvis du ikke har skiftet din kode, så skift venligst din kode ved at klikke på linket herunder' + CHANGEPASSWORDTEXT1: 'Du skiftede dit kodeord for' + CHANGEPASSWORDTEXT3: 'Skift kodeord' + HELLO: Hej + SilverStripe\Control\Email\ForgotPasswordEmail_ss: + HELLO: Hej + TEXT1: 'Her er din' + TEXT2: 'link til at nulstille dit kodeord' + TEXT3: for + SilverStripe\Control\RequestProcessor: + INVALID_REQUEST: 'Ugyldig forespørgsel' + REQUEST_ABORTED: 'Forespørgsel annulleret' + SilverStripe\Core\Manifest\VersionProvider: + VERSIONUNKNOWN: Ukendt + SilverStripe\Forms\CheckboxField: + NOANSWER: Nej + YESANSWER: Ja + SilverStripe\Forms\CheckboxSetField_ss: + NOOPTIONSAVAILABLE: 'Ingen tilgængelige muligheder' + SilverStripe\Forms\ConfirmedPasswordField: + ATLEAST: 'Kodeord skal være mindst {min} tegn lang.' + BETWEEN: 'Kodeord skal være {min} til {max} karakterer lang.' + CURRENT_PASSWORD_ERROR: 'Det nuværende kodeord du har indtastet er ikke korrekt.' + CURRENT_PASSWORD_MISSING: 'Du skal indtaste dit nuværende kodeord.' + LOGGED_IN_ERROR: 'Du skal være logget ind for at skifte dit kodeord.' + MAXIMUM: 'Kodeord må maks være {max} tegn lang' + SHOWONCLICKTITLE: 'Skift kodeord' + SilverStripe\Forms\CurrencyField: + CURRENCYSYMBOL: DKK + SilverStripe\Forms\DateField: + VALIDDATEFORMAT2: 'Indtats venligst et gyldigt datoformat ({format})' + VALIDDATEMAXDATE: 'Din dato skal være ældre end eller matche den maksimalt tilladte dato ({date})' + VALIDDATEMINDATE: 'Din dato skal være yngre end eller matche den minimum tilladte dato ({date})' + SilverStripe\Forms\DatetimeField: + VALIDDATEMAXDATETIME: 'Din dato skal være ældre end eller matche den maksimalt tilladte dato ({datetime})' + VALIDDATETIMEFORMAT: 'Indtats venligst et gyldigt dato- og tidsformat ({format})' + VALIDDATETIMEMINDATE: 'Din dato skal være yngre end eller matche den minimum tilladte dato og tid ({datetime})' + SilverStripe\Forms\DropdownField: + CHOOSE: (Vælg) + CHOOSE_MODEL: '(Vælg {name})' + SOURCE_VALIDATION: 'Venligst vælg en eksisterende værdi fra listen. {value} er ikke en tilladt mulighed' + SilverStripe\Forms\EmailField: + VALIDATION: 'Indtast venligst en emailadresse' + SilverStripe\Forms\FileUploadReceiver: + FIELDNOTSET: 'Fil information ikke fundet' + SilverStripe\Forms\Form: + BAD_METHOD: 'Denne form kræver en {method} indsendelse' + CSRF_EXPIRED_MESSAGE: 'Din session er udløbet. Venligst gensend formularen.' + CSRF_FAILED_MESSAGE: 'Det ser ud til der har været et teknisk problem. Klik venligst på tilbageknappen, tryk opdater i din browser og prøv igen.' + VALIDATIONPASSWORDSDONTMATCH: 'Kodeordene er ikke identiske' + VALIDATIONPASSWORDSNOTEMPTY: 'Kodeord kan ikke være tomme' + VALIDATIONSTRONGPASSWORD: 'Kodeord skal mindst have et tal og et alfanumerisk tegn' + VALIDATOR: Validering + VALIDCURRENCY: 'Indtast venligst en gyldig valuta' + SilverStripe\Forms\FormField: + EXAMPLE: 'f.eks. {format}' + NONE: ingen + SilverStripe\Forms\FormScaffolder: + TABMAIN: Primær SilverStripe\Forms\GridField\GridField: - Filter: Filter + Add: 'Tilføj {name}' + CSVEXPORT: 'Eksporter til CSV' + CSVIMPORT: 'Importer CSV' + Filter: Filtrer + FilterBy: 'Filtrer på' + Find: Find + LinkExisting: 'Link eksisterende' + NewRecord: 'Ny {type}' + NoItemsFound: 'Ingen elementer fundet' + PRINTEDAT: 'Printet d.' + PRINTEDBY: 'Printet af' + PlaceHolder: 'Find {type}' + PlaceHolderWithLabels: 'Find {type} på {name}' + Print: Print + RelationSearch: Relationssøgning + ResetFilter: Nulstil + SilverStripe\Forms\GridField\GridFieldDeleteAction: + Delete: Slet + DeletePermissionsFailure: 'Ingen slette rettigheder' + EditPermissionsFailure: 'Ingen rettighed til at fjerne emnet' + UnlinkRelation: Fjern + SilverStripe\Forms\GridField\GridFieldDetailForm: + CancelBtn: Annuller + Create: Opret + Delete: Slet + DeletePermissionsFailure: 'Ingen slette rettigheder' + Deleted: 'Slet {type} {name}' + Save: Gem + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Kan ikke fjerne dig selv fra denne gruppe, du vil miste administrator rettigheder' + SilverStripe\Forms\GridField\GridFieldPaginator: + OF: af + Page: Side + View: Vis + SilverStripe\Forms\MoneyField: + FIELDLABELAMOUNT: Beløb + FIELDLABELCURRENCY: Valuta + INVALID_CURRENCY: 'Valuta {currency} er ikke i listen over tilladte valutaer' + SilverStripe\Forms\MultiSelectField: + SOURCE_VALIDATION: 'Vælg venligst eksisterende værdier fra listen. Ugyldig mulighed(er) {value} valgt' + SilverStripe\Forms\NullableField: + IsNullLabel: 'Er Null' + SilverStripe\Forms\NumericField: + VALIDATION: '''{value}'' er ikke et tal, kun tal accepteres i dette felt' + SilverStripe\Forms\TimeField: + VALIDATEFORMAT: 'Indtats venligst et gyldigt tidsformat ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: Dataobjekter + PLURALS: + one: 'Et dataobjekt' + other: '{count} dataobjekter' + SINGULARNAME: Dataobjekt + SilverStripe\ORM\FieldType\DBBoolean: + ANY: Enhver + NOANSWER: Nej + YESANSWER: Ja + SilverStripe\ORM\FieldType\DBDate: + DAYS_SHORT_PLURALS: + one: '{count} dag' + other: '{count} dage' + HOURS_SHORT_PLURALS: + one: '{count} time' + other: '{count} timer' + LessThanMinuteAgo: 'mindre end et minut' + MINUTES_SHORT_PLURALS: + one: '{count} minut' + other: '{count} minutter' + MONTHS_SHORT_PLURALS: + one: '{count} måned' + other: '{count} måneder' + SECONDS_SHORT_PLURALS: + one: '{count} sekund' + other: '{count} sekunder' + TIMEDIFFAGO: '{difference} siden' + TIMEDIFFIN: 'i {difference}' + YEARS_SHORT_PLURALS: + one: '{count} år' + other: '{count} år' + SilverStripe\ORM\FieldType\DBEnum: + ANY: Enhver + SilverStripe\ORM\Hierarchy: + LIMITED_TITLE: 'For mange underelementer ({count})' + SilverStripe\ORM\Hierarchy\Hierarchy: + InfiniteLoopNotAllowed: 'Uendeligt løkke fundet i "{type}" hierarkiet. Ændre venligst det overliggende element for at løse dette' + LIMITED_TITLE: 'For mange underelementer ({count})' + SilverStripe\ORM\ValidationException: + DEFAULT_ERROR: Valideringsfejl + SilverStripe\Security\BasicAuth: + ENTERINFO: 'Indtast venligst et brugernavn og kodeord.' + ERRORNOTADMIN: 'Den bruger er ikke en administrator.' + ERRORNOTREC: 'Brugernavn / kodeord kunne ikke genkendes' + SilverStripe\Security\CMSMemberLoginForm: + PASSWORDEXPIRED: '

Dit kodeord er udløbet. Vælg venligst et nyt.

' + SilverStripe\Security\CMSSecurity: + INVALIDUSER: '

Ugyldig bruger. Log venligst ind igen her for at fortsætte.

' + LOGIN_MESSAGE: '

Din session er løbet ud pga. inaktivitet

' + LOGIN_TITLE: 'Log ind igen, for at fortsætte hvor du slap.' + SUCCESS: Succes + SUCCESSCONTENT: '

Logget ind. Hvis du ikke automatisk viderestilles så klik her

' + SUCCESS_TITLE: 'Logget ind med sucess' + SilverStripe\Security\DefaultAdminService: + DefaultAdminFirstname: 'Standard admin' + SilverStripe\Security\Group: + AddRole: 'Tilføj en rolle for denne gruppe' + Code: 'Gruppe kode' + DefaultGroupTitleAdministrators: Administratorer + DefaultGroupTitleContentAuthors: Indholdsforfattere + Description: Beskrivelse + GROUPNAME: Gruppenavn + GroupReminder: 'Hvis du vælger en overliggende gruppe, får denne gruppe alle dens roller' + HierarchyPermsError: 'Kan ikke tildele overliggende gruppe "{group}" med fortrinsrettigheder (kræver ADMIN adgang)' + Locked: 'Låst?' + MEMBERS: Brugere + NEWGROUP: 'Ny gruppe' + NoRoles: 'Ingen roller fundet' + PERMISSIONS: Rettigheder + PLURALNAME: Grupper + PLURALS: + one: 'En gruppe' + other: '{count} grupper' + Parent: 'Overliggende gruppe' + ROLES: Roller + ROLESDESCRIPTION: 'Roller er et prædefineret sæt af rettigheder, som kan tildeles grupper.
De bliver nedarvet fra en overliggende grupper hvis krævet.' + RolesAddEditLink: 'Administrer roller' + SINGULARNAME: Gruppe + Sort: Sortering + has_many_Permissions: Rettigheder + many_many_Members: Brugere + SilverStripe\Security\LoginAttempt: + Email: 'Email adresse' + EmailHashed: 'Email adresse (hashed)' + IP: 'IP addresse' + PLURALNAME: Loginforsøg + PLURALS: + one: 'Et loginforsøg' + other: '{count} loginforsøg' + SINGULARNAME: 'Login forsøg' + Status: Status + SilverStripe\Security\Member: + ADDGROUP: 'Tilføj gruppe' + BUTTONCHANGEPASSWORD: 'Skift kodeord' + BUTTONLOGIN: 'Log ind' + BUTTONLOGINOTHER: 'Log ind med en anden bruger' + BUTTONLOGOUT: 'Log ud' + BUTTONLOSTPASSWORD: 'Jeg har glemt mit kodeord' + CONFIRMNEWPASSWORD: 'Bekræft nyt kodeord' + CONFIRMPASSWORD: 'Bekræft kodeord' + CURRENT_PASSWORD: 'Nuværende kodeord' + EDIT_PASSWORD: 'Nyt kodeord' + EMAIL: Email + EMPTYNEWPASSWORD: 'Det nye kodeord kan ikke være tom, prøv venligst igen' + ENTEREMAIL: 'Indtast venligst en email adresse for at få et nulstillingslink.' + ERRORLOCKEDOUT2: 'Din konto er blevet midlertidigt deaktiveret pga. for mange fejlslagne loginforsøg. Forsøg venligst igen om {count} minutter.' + ERRORNEWPASSWORD: 'Du har indtastet dit nye kodeord forskelligt, forsøg igen' + ERRORPASSWORDNOTMATCH: 'Dit nuværende kodeord matcher ikke, forsøg venligst igen' + ERRORWRONGCRED: 'De indtastede værdier ser ikke ud til at være korrekte. Forsøg venligst igen.' + FIRSTNAME: Fornavn + INTERFACELANG: 'Sprog i brugerfladen' + KEEPMESIGNEDIN: 'Hold mig logget ind' + LOGGEDINAS: 'Du er logget ind som {name}.' + NEWPASSWORD: 'Nyt kodeord' + PASSWORD: Kodeord + PASSWORDEXPIRED: 'Dit kodeord er udløbet. Vælg venligst et nyt.' + PLURALNAME: Brugere + PLURALS: + one: 'En bruger' + other: '{count} brugere' + REMEMBERME: 'Husk mig til næste gang? (i {count} dage på denne enhed)' + SINGULARNAME: Bruger + SUBJECTPASSWORDCHANGED: 'Dit kodeord er blevet ændret' + SUBJECTPASSWORDRESET: 'Link til at nulstille dit kodeord' + SURNAME: Efternavn + VALIDATIONADMINLOSTACCESS: 'Kan ikke fjerne alle admin grupper fra din profil' + ValidationIdentifierFailed: 'Kan ikke overskrive eksisterende bruger #{id} med identisk identifikator ({name} = {value}))' + WELCOMEBACK: 'Velkommen tilbage, {firstname}' + YOUROLDPASSWORD: 'Dit gamle kodeord' + belongs_many_many_Groups: Grupper + db_Locale: 'Sprog i brugerfladen' + db_LockedOutUntil: 'Låst ude indtil' + db_Password: Kodeord + db_PasswordExpiry: Kodeordsudløbsdato + SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: + AUTHENTICATORNAME: 'CMS bruger loginform' + BUTTONFORGOTPASSWORD: 'Glemt kodeord' + BUTTONLOGIN: 'Log mig ind igen' + BUTTONLOGOUT: 'Log ud' + SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: + ERRORWRONGCRED: 'De indtastede værdier ser ikke ud til at være korrekte. Forsøg venligst igen.' + NoPassword: 'Der er ikke en kode på denne bruger.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'Email og kodeord' + SilverStripe\Security\MemberPassword: + PLURALNAME: 'Bruger kodeord' + PLURALS: + one: 'Et bruger kodeord' + other: '{count} bruger kodeord' + SINGULARNAME: 'Bruger kodeord' + SilverStripe\Security\PasswordValidator: + LOWCHARSTRENGTH: 'Forøg venligst kodeordets styrke, ved at tilføje nogle af følgende tegn: {chars}' + PREVPASSWORD: 'Du har tidligere brugt dette kodeord, vælg venligst et nyt kodeord' + TOOSHORT: 'Kodeordet er for kort, det skal mindst være {minimum} eller flere tegn langt' SilverStripe\Security\Permission: + AdminGroup: Administrator + CMS_ACCESS_CATEGORY: 'CMS Adgang' CONTENT_CATEGORY: Indholdsrettigheder + FULLADMINRIGHTS: 'Fuld administrator rettighed' + FULLADMINRIGHTS_HELP: 'Indebærer og overskriver alle andre tildelte rettigheder.' + PERMISSIONS_CATEGORY: 'Roller og adgangsrettigheder' + PLURALNAME: Rettigheder + PLURALS: + one: 'En rettighed' + other: '{count} rettigheder' + SINGULARNAME: Rettighed + UserPermissionsIntro: 'Tildeling af grupper til denne bruger, ændrer de rettigheder brugeren har. Se gruppe området for rettigheds detaljer på de individuelle grupper.' + SilverStripe\Security\PermissionCheckboxSetField: + AssignedTo: 'tildelt til "{title}"' + FromGroup: 'nedarvet fra gruppen "{title}"' + FromRole: 'nedarvet fra rollen "{title}"' + FromRoleOnGroup: 'nedarvet fra rollen "{roletitle}" på gruppen "{grouptitle}"' + SilverStripe\Security\PermissionRole: + OnlyAdminCanApply: 'Kun administratorer kan tilføje' + PLURALNAME: Roller + PLURALS: + one: 'En rolle' + other: '{count} roller' + SINGULARNAME: Rolle + Title: Titel + SilverStripe\Security\PermissionRoleCode: + PLURALNAME: 'Rettigheds rolle koder' + PLURALS: + one: 'En rettigheds rolle kode' + other: '{count} rettigheds rolle koder' + PermsError: 'Kan ikke tildele koden "{code}" med fortrinsrettigheder (kræver ADMIN adgang)' + SINGULARNAME: 'Rettighed rolle kode' + SilverStripe\Security\RememberLoginHash: + PLURALNAME: 'Login hashes' + PLURALS: + one: 'Et login hash' + other: '{count} Login Hashes' + SINGULARNAME: 'Login hash' + SilverStripe\Security\Security: + ALREADYLOGGEDIN: 'Du har ikke adgang til denne side. Hvis du har en anden bruger der har adgang til denne side, kan du logge ind med denne herunder.' + BUTTONSEND: 'Send mig linket til at nulstille kodeordet' + CHANGEPASSWORDBELOW: 'Du kan ændre dit kodeord herunder.' + CHANGEPASSWORDHEADER: 'Skift dit kodeord' + CONFIRMLOGOUT: 'Klik venligst på knappen herunder, for at bekræfte at du vil logge ud.' + ENTERNEWPASSWORD: 'Indtast venligst et nyt kodeord.' + ERRORPASSWORDPERMISSION: 'Du skal være logget ind, for at kunne ændre dit kodeord!' + LOGIN: 'Log ind' + LOGOUT: 'Log ud' + LOSTPASSWORDHEADER: 'Glemt kodeord' + NOTEPAGESECURED: 'Denne side er beskyttet. Indtast dine loginoplysninger herunder for at få adgang.' + NOTERESETPASSWORD: 'Indtast din email adresse, så sender vi dig et link som du kan nulstille dit kodeord med' diff --git a/lang/de.yml b/lang/de.yml index 3bbf8cdb5..77e2f1584 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -11,8 +11,6 @@ de: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: € SilverStripe\Forms\DateField: - NOTSET: 'nicht gesetzt' - TODAY: heute VALIDDATEFORMAT2: 'Bitte geben sie das Datum im korrekten Format ein ({format})' VALIDDATEMAXDATE: 'Ihr Datum muss vor dem erlaubtem Datum ({date}) liegen oder gleich sein' VALIDDATEMINDATE: 'Ihr Datum muss nach dem erlaubtem Datum ({date}) liegen oder gleich sein' @@ -49,7 +47,6 @@ de: RelationSearch: Relationssuche ResetFilter: Zurücksetzen SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Löschen Delete: Löschen DeletePermissionsFailure: 'Keine Berechtigung zum Löschen' EditPermissionsFailure: 'Sie haben keine Berechtigung, die Verknüpfung zu lösen' @@ -61,8 +58,6 @@ de: DeletePermissionsFailure: 'Keine Berechtigungen zum löschen' Deleted: 'Gelöscht {type} {name}' Save: Speichern - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Bearbeiten SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Betrag FIELDLABELCURRENCY: Währung @@ -195,7 +190,4 @@ de: LOGIN: Anmelden LOSTPASSWORDHEADER: 'Passwort vergessen' NOTEPAGESECURED: 'Diese Seite ist geschützt. Bitte melden Sie sich an und Sie werden sofort weitergeleitet.' - NOTERESETLINKINVALID: '

Der Link zum Zurücksetzen des Passworts ist entweder nicht korrekt oder abgelaufen

Sie können einen neuen Link anfordern oder Ihr Passwort nach dem einloggen ändern.

' NOTERESETPASSWORD: 'Geben Sie Ihre E-Mail-Adresse ein und wir werden Ihnen einen Link zuschicken, mit dem Sie Ihr Passwort zurücksetzen können.' - PASSWORDSENTHEADER: 'Der Link zum Zurücksetzen des Passworts wurde an ''{email}'' gesendet' - PASSWORDSENTTEXT: 'Vielen Dank! Wenn ein Account zu der E-Mail Adresse ''{email}'' existiert, wurde eine E-Mail mit dem Link zum Zurücksetzen des Passworts verschickt.' diff --git a/lang/de_DE.yml b/lang/de_DE.yml new file mode 100644 index 000000000..e1bea0c6e --- /dev/null +++ b/lang/de_DE.yml @@ -0,0 +1,159 @@ +de_DE: + SilverStripe\Admin\LeftAndMain: + VersionUnknown: Unbekannt + SilverStripe\AssetAdmin\Forms\UploadField: + Dimensions: Maße + EDIT: Bearbeiten + EDITINFO: 'Datei bearbeiten' + REMOVE: Entfernen + SilverStripe\Control\ChangePasswordEmail_ss: + CHANGEPASSWORDFOREMAIL: 'Das Passwort für das Konto mit der E-Mail-Adresse {email} wurde geändert. Wenn Sie Ihr Passwort nicht geändert haben, ändern Sie bitte Ihr Passwort mit dem folgenden Link' + CHANGEPASSWORDTEXT1: 'Sie haben Ihr Passwort für geändert' + CHANGEPASSWORDTEXT3: 'Passwort ändern' + HELLO: Hallo + SilverStripe\Control\Email\ForgotPasswordEmail_ss: + HELLO: Hallo + TEXT1: 'Hier ist dein' + TEXT2: 'Link zum Zurücksetzen des Passworts' + TEXT3: für + SilverStripe\Core\Manifest\VersionProvider: + VERSIONUNKNOWN: Unbekannt + SilverStripe\Forms\CheckboxField: + NOANSWER: Nein + YESANSWER: Ja + SilverStripe\Forms\CheckboxSetField_ss: + NOOPTIONSAVAILABLE: 'Keine Optionen vorhanden' + SilverStripe\Forms\ConfirmedPasswordField: + ATLEAST: 'Passwörter müssen mindestens {min} Zeichen lang sein.' + BETWEEN: 'Passwörter müssen {min} bis {max} Zeichen lang sein.' + SHOWONCLICKTITLE: 'Passwort ändern' + SilverStripe\Forms\DateField: + TODAY: heute + SilverStripe\Forms\DropdownField: + CHOOSE: (Auswählen) + CHOOSE_MODEL: '({name} auswählen)' + SilverStripe\Forms\GridField\GridField: + Add: '{name} hinzufügen' + CSVEXPORT: 'Als CSV exportieren' + CSVIMPORT: 'CSV importieren' + Filter: Filtern + FilterBy: 'Filtern nach' + Print: Drucken + ResetFilter: Zurücksetzen + SilverStripe\Forms\GridField\GridFieldDeleteAction: + Delete: Löschen + SilverStripe\Forms\GridField\GridFieldDetailForm: + CancelBtn: Abbrechen + Save: Speichern + SilverStripe\Forms\GridField\GridFieldEditButton: + EDIT: Bearbeiten + SilverStripe\Forms\GridField\GridFieldFilterHeader: + Search: 'Suche "{name}"' + SilverStripe\Forms\GridField\GridFieldPaginator: + Page: Seite + SilverStripe\Forms\MoneyField: + FIELDLABELAMOUNT: Betrag + FIELDLABELCURRENCY: Währung + INVALID_CURRENCY: 'Die Währung {currency} ist nicht in der Liste der erlauben Währungen' + SilverStripe\ORM\DataObject: + PLURALNAME: DatenObjekte + PLURALS: + one: 'Ein DatenObjekt' + other: '{count} DatenObjekte' + SINGULARNAME: DatenObjekt + SilverStripe\ORM\FieldType\DBBoolean: + NOANSWER: Nein + YESANSWER: Ja + SilverStripe\ORM\FieldType\DBDate: + DAYS_SHORT_PLURALS: + one: '{count} Tag' + other: '{count} Tage' + HOURS_SHORT_PLURALS: + one: '{count} Stunde' + other: '{count} Stunden' + LessThanMinuteAgo: 'weniger als 1 Minute' + MINUTES_SHORT_PLURALS: + one: '{count} Minute' + other: '{count} Minuten' + MONTHS_SHORT_PLURALS: + one: '{count} Monat' + other: '{count} Monate' + SECONDS_SHORT_PLURALS: + one: '{count} Sekunde' + other: '{count} Sekunden' + TIMEDIFFAGO: 'vor {difference}' + TIMEDIFFIN: 'in {difference}' + YEARS_SHORT_PLURALS: + one: '{count} Jahr' + other: '{count} Jahre' + SilverStripe\Security\BasicAuth: + ENTERINFO: 'Bitte geben Sie einen Benutzernamen und ein Passwort ein' + ERRORNOTADMIN: 'Dieser Benutzer ist kein Administrator' + ERRORNOTREC: 'Dieser Benutzer bzw. dieses Passwort ist unbekannt' + SilverStripe\Security\CMSMemberLoginForm: + PASSWORDEXPIRED: '

Ihr Passwort ist abgelaufen. Bitte wählen Sie ein neues Passwort.

' + SilverStripe\Security\CMSSecurity: + SUCCESS_TITLE: 'Login erfolgreich' + SilverStripe\Security\DefaultAdminService: + DefaultAdminFirstname: 'Standard Administrator' + SilverStripe\Security\Group: + DefaultGroupTitleAdministrators: Administratoren + DefaultGroupTitleContentAuthors: Inhaltsautoren + Description: Beschreibung + GROUPNAME: Gruppenname + MEMBERS: Mitglieder + NEWGROUP: 'Neue Gruppe' + NoRoles: 'Keine Rollen gefunden' + PLURALNAME: Gruppen + PLURALS: + one: 'Eine Gruppe' + other: '{count} Gruppen' + SINGULARNAME: Gruppe + Sort: Sortierreihenfolge + has_many_Permissions: Rechte + many_many_Members: Mitglieder + SilverStripe\Security\LoginAttempt: + Email: 'E-Mail Adresse' + EmailHashed: 'E-Mail Adresse (gehasht)' + IP: 'IP Adresse' + PLURALNAME: Loginversuche + PLURALS: + one: 'Ein Loginversuch' + other: '{count} Loginversuche' + SINGULARNAME: Loginversuch + Status: Status + SilverStripe\Security\Member: + ADDGROUP: 'Gruppe hinzufügen' + BUTTONCHANGEPASSWORD: 'Passwort ändern' + BUTTONLOGIN: Einloggen + BUTTONLOGINOTHER: 'Als jemand anderes einloggen' + BUTTONLOGOUT: Ausloggen + BUTTONLOSTPASSWORD: 'Ich habe mein Passwort vergessen' + CONFIRMNEWPASSWORD: 'Neues Passwort bestätigen' + CONFIRMPASSWORD: 'Passwort bestätigen' + CURRENT_PASSWORD: 'Derzeitiges Passwort' + EDIT_PASSWORD: 'Neues Passwort' + EMAIL: E-Mail + EMPTYNEWPASSWORD: 'Das neue Passwort kann nicht leer sein, bitte versuchen Sie es erneut' + ENTEREMAIL: 'Bitte geben Sie Ihre E-Mail Adresse an. Sie erhalten eine E-Mail mit einem Link zum Zurücksetzen des Passworts.' + FIRSTNAME: Vorname + NEWPASSWORD: 'Neues Passwort' + PASSWORD: Passwort + PASSWORDEXPIRED: 'Ihr Passwort ist abgelaufen. Bitte wählen Sie ein neues Passwort.' + PLURALNAME: Mitglieder + PLURALS: + one: 'Ein Mitglied' + other: '{count} Mitglieder' + SINGULARNAME: Mitglied + SURNAME: Nachname + WELCOMEBACK: 'Willkommen zurück, {firstname}' + YOUROLDPASSWORD: 'Ihr altes Passwort' + belongs_many_many_Groups: Grouppen + db_Password: Passwort + SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: + BUTTONFORGOTPASSWORD: 'Passwort vergessen' + SilverStripe\Security\Permission: + AdminGroup: Administrator + SilverStripe\Security\Security: + LOGIN: Einloggen + LOGOUT: Ausloggen diff --git a/lang/en.yml b/lang/en.yml index ef6596a01..2a6fa6c18 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -37,8 +37,6 @@ en: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'not set' - TODAY: today VALIDDATEFORMAT2: 'Please enter a valid date format ({format})' VALIDDATEMAXDATE: 'Your date has to be older or matching the maximum allowed date ({date})' VALIDDATEMINDATE: 'Your date has to be newer or matching the minimum allowed date ({date})' diff --git a/lang/eo.yml b/lang/eo.yml index 6660d9b1b..cc792bab4 100644 --- a/lang/eo.yml +++ b/lang/eo.yml @@ -37,8 +37,6 @@ eo: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'ne agordita' - TODAY: hodiaŭ VALIDDATEFORMAT2: 'Bonvole enigu validan datan formaton ({format})' VALIDDATEMAXDATE: 'Necesas ke via dato estu pli aĝa ol, aŭ egala al la maksimuma permesita dato ({date})' VALIDDATEMINDATE: 'Necesas ke via dato estu pli nova ol, aŭ egala al la minimuma permesita dato ({date})' @@ -86,7 +84,6 @@ eo: RelationSearch: 'Serĉi rilatojn' ResetFilter: Restartigi SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Forigi Delete: Forigi DeletePermissionsFailure: 'Mankas permeso forigi' EditPermissionsFailure: 'Mankas permeso malligi rikordon' @@ -98,23 +95,12 @@ eo: DeletePermissionsFailure: 'Mankas permeso forigi' Deleted: 'Forigita {type} {name}' Save: Konservi - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Redakti SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: UnlinkSelfFailure: 'Ne povas forigi vin el ĉi tiu grupo; vi perdus administrajn rajtojn' SilverStripe\Forms\GridField\GridFieldPaginator: OF: de Page: Paĝo View: Vido - SilverStripe\Forms\GridField\GridFieldVersionedState: - ADDEDTODRAFTHELP: 'Ero ankoraŭ estas ne publikigita' - ADDEDTODRAFTSHORT: Malneto - ARCHIVEDPAGEHELP: 'Ero estas forigita el malneta kaj publika' - ARCHIVEDPAGESHORT: Enarkivigita - MODIFIEDONDRAFTHELP: 'Ero enhavas nepublikigitajn ŝanĝojn' - MODIFIEDONDRAFTSHORT: Ŝanĝita - ONLIVEONLYSHORT: 'Nur ĉe publika' - ONLIVEONLYSHORTHELP: 'Ero estas publikigita, sed ĝi estas forigita el malneto' SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Kvanto FIELDLABELCURRENCY: Kurzo @@ -270,6 +256,8 @@ eo: SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: ERRORWRONGCRED: 'La donitaj detaloj ŝajnas malĝustaj. Bonvole reprovu.' NoPassword: 'Mankas pasvorto por ĉi tiu membro.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'Retpoŝtadreso kaj pasvorto' SilverStripe\Security\MemberPassword: PLURALNAME: 'Membraj pasvortoj' PLURALS: @@ -331,7 +319,4 @@ eo: LOGOUT: Elsaluti LOSTPASSWORDHEADER: 'Perdis pasvorton' NOTEPAGESECURED: 'Tiu paĝo estas sekurigita. Enigu viajn akreditaĵojn sube kaj vi aliros pluen.' - NOTERESETLINKINVALID: '

La pasvorta reagorda ligilo estas malvalida aŭ finiĝis.

Vi povas peti novan ĉi tie aŭ ŝanĝi vian pasvorton post vi ensalutis.

' NOTERESETPASSWORD: 'Enigu vian retpoŝtan adreson kaj ni sendos al vi ligilon per kiu vi povas reagordi vian pasvorton' - PASSWORDSENTHEADER: 'Pasvorta reagorda ligilo sendiĝis al ''{email}''' - PASSWORDSENTTEXT: 'Dankon! Reagordita ligilo sendiĝis al ''{email}'', kondiĉe ke konto ekzistas por tiu retadreso.' diff --git a/lang/es.yml b/lang/es.yml index 5251bdbf6..debd4b4a7 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -15,8 +15,6 @@ es: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: Símbolo SilverStripe\Forms\DateField: - NOTSET: 'sin establecer' - TODAY: hoy VALIDDATEFORMAT2: 'Por favor, introduzca un formato de fecha válido ({format})' VALIDDATEMAXDATE: 'La fecha tiene que ser mayor o igual a la fecha máxima permitida ({date})' VALIDDATEMINDATE: 'La fecha tiene que ser posterior o coincidente a la fecha mínima permitida ({date})' @@ -55,7 +53,6 @@ es: RelationSearch: 'Búsqueda de relación' ResetFilter: Restaurar SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Borrar Delete: Borrar DeletePermissionsFailure: 'Sin permiso para borrar' EditPermissionsFailure: 'No se pudo editar permisos' @@ -67,8 +64,6 @@ es: DeletePermissionsFailure: 'Sin permiso para borrar' Deleted: 'Borrado {type} {name}' Save: Guardar - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Editar SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Cantidad FIELDLABELCURRENCY: Moneda @@ -254,7 +249,4 @@ es: LOGIN: Entrar LOSTPASSWORDHEADER: '¿Contraseña Perdida?' NOTEPAGESECURED: 'Esa página está protegida. Introduzca sus datos de acreditación a continuación y lo enviaremos a ella en un momento.' - NOTERESETLINKINVALID: '

El enlace para restablecer la contraseña es inválido o ha expirado.

Usted puede solicitar uno nuevo aqui o cambiar su contraseña después de que se haya conectado.

' NOTERESETPASSWORD: 'Introduzca su dirección de e-mail, y le enviaremos un enlace, con el cual podrá restaurar su contraseña' - PASSWORDSENTHEADER: 'Un enlace para restablecer la contraseña ha sido enviado a ''{email}''' - PASSWORDSENTTEXT: 'Gracias! Un enlace para restablecer la contraseña ha sido enviado a ''{email}'', siempre que una cuenta exista para la dirección de email indicada.' diff --git a/lang/es_AR.yml b/lang/es_AR.yml index 3539b9101..773d79948 100644 --- a/lang/es_AR.yml +++ b/lang/es_AR.yml @@ -1,9 +1,6 @@ es_AR: SilverStripe\Forms\ConfirmedPasswordField: SHOWONCLICKTITLE: 'Cambiar Contraseña' - SilverStripe\Forms\DateField: - NOTSET: 'no especificada' - TODAY: hoy SilverStripe\Forms\DropdownField: CHOOSE: (Selecciona) SilverStripe\Forms\Form: diff --git a/lang/es_MX.yml b/lang/es_MX.yml index 5fd337559..04baa70a6 100644 --- a/lang/es_MX.yml +++ b/lang/es_MX.yml @@ -2,8 +2,6 @@ es_MX: SilverStripe\Forms\ConfirmedPasswordField: SHOWONCLICKTITLE: 'Cambiar contraseña' SilverStripe\Forms\DateField: - NOTSET: 'no especificada' - TODAY: ahora VALIDDATEFORMAT2: 'Por favor ingresar un formato válido de fecha ({format})' VALIDDATEMAXDATE: 'Tu fecha tiene que ser más antigua o al menos coincidir con la fecha mínima permitida ({date})' VALIDDATEMINDATE: 'Tu fecha tiene que ser nueva o al menos coincidir con la fecha mínima permitida ({date})' diff --git a/lang/et_EE.yml b/lang/et_EE.yml index 2c44eee9b..a8fb3b686 100644 --- a/lang/et_EE.yml +++ b/lang/et_EE.yml @@ -8,8 +8,6 @@ et_EE: MAXIMUM: 'Parool võib olla kuni {max} märki pikk.' SHOWONCLICKTITLE: 'Muuda parool' SilverStripe\Forms\DateField: - NOTSET: 'Pole seadistatud' - TODAY: Täna VALIDDATEFORMAT2: 'Sisestage sobivas vormingus kuupäev ({format})' VALIDDATEMAXDATE: 'Teie kuupäev peab oleme lubatud kuupäevast ({date}) varasem või ühtima sellega.' VALIDDATEMINDATE: 'Teie kuupäev peab oleme lubatud kuupäevast ({date}) hilisem või ühtima sellega.' @@ -41,7 +39,6 @@ et_EE: RelationSearch: 'Seose otsing' ResetFilter: Lähtesta SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Kustuta Delete: Kustuta DeletePermissionsFailure: 'Kustutamisõigused puuduvad' UnlinkRelation: 'Tühista linkimine' @@ -52,8 +49,6 @@ et_EE: DeletePermissionsFailure: 'Kustutamisõigused puuduvad' Deleted: '{type} {name} on kustutatud' Save: Salvesta - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Redigeeri SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Hulk FIELDLABELCURRENCY: Valuuta @@ -144,7 +139,4 @@ et_EE: ERRORPASSWORDPERMISSION: 'Pead olema sisseloginud, et parooli muuta!' LOGIN: 'Logi sisse' NOTEPAGESECURED: 'See leht on turvatud. Sisesta enda andmed allpool ja me saadame sind otse edasi' - NOTERESETLINKINVALID: '

Parooli lähtestamise link on kehtetu või aegunud.

Saate taotleda uut linki siin või muuta parooli pärast sisselogimist.

' NOTERESETPASSWORD: 'Sisesta oma email ja me saadame sulle lingi kus saad oma parooli tühistada.' - PASSWORDSENTHEADER: 'Parooli lähtestamise link saadeti aadressile ''{email}''' - PASSWORDSENTTEXT: 'Aitäh! Lähtestamislink saadeti aadressile ''{email}'' eeldusel, et selle e-posti aadressiga seotud konto on olemas.' diff --git a/lang/fa_IR.yml b/lang/fa_IR.yml index 14c967ba9..b9aa0ebea 100644 --- a/lang/fa_IR.yml +++ b/lang/fa_IR.yml @@ -13,8 +13,6 @@ fa_IR: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: ﷼ SilverStripe\Forms\DateField: - NOTSET: نامشخص - TODAY: امروز VALIDDATEFORMAT2: 'لطفاً یک قالب تاریخ معتبر وارد نمایید ({format})' VALIDDATEMAXDATE: 'تاریخ شما باید قدیمی‌تر یا برابر با حداکثر تاریخ مجاز ({date}) باشد' VALIDDATEMINDATE: 'تاریخ شما باید جدیدتر یا برابر با حداقل تاریخ مجاز ({date}) باشد' @@ -50,7 +48,6 @@ fa_IR: RelationSearch: 'جستجوی رابط' ResetFilter: 'از نو' SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: حذف Delete: حذف DeletePermissionsFailure: 'دسترسی‌های حذف وجود ندارد' EditPermissionsFailure: 'دسترسی‌های حذف لینک وجود ندارد' @@ -62,8 +59,6 @@ fa_IR: DeletePermissionsFailure: 'دسترسی‌های حذف وجود ندارد' Deleted: 'حذف شده {type} {name}' Save: ذخیره - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: ویرایش SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: مقدار FIELDLABELCURRENCY: 'واحد پول' @@ -173,4 +168,3 @@ fa_IR: ERRORPASSWORDPERMISSION: 'جهت تغییر گذرواژه خود باید وارد شده باشید!' LOGIN: ورود LOSTPASSWORDHEADER: 'فراموشی گذرواژه' - PASSWORDSENTHEADER: 'لینک ازنوسازی گذرواژه به ''{email}'' ارسال شد' diff --git a/lang/fi.yml b/lang/fi.yml index 53eae99ed..01899f2af 100644 --- a/lang/fi.yml +++ b/lang/fi.yml @@ -37,8 +37,6 @@ fi: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'ei asetettu' - TODAY: tänään VALIDDATEFORMAT2: 'Ole hyvä ja kirjaa päivämäärä sallitussa muodossa ({format})' VALIDDATEMAXDATE: 'Päivämäärän on oltava vanhempi tai sovittava asetettuun maksimiin ({date})' VALIDDATEMINDATE: 'Päivämäärän on oltava uudempi tai sovittava asetettuun minimiin ({date})' @@ -86,7 +84,6 @@ fi: RelationSearch: Relaatiohaku ResetFilter: Nollaa SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Poista Delete: Poista DeletePermissionsFailure: 'Ei oikeuksia poistamiseen' EditPermissionsFailure: 'Ei oikeuksia purkaa linkitystä tietueeseen' @@ -98,23 +95,12 @@ fi: DeletePermissionsFailure: 'Ei oikeuksia poistamiseen' Deleted: 'Poistettiin {type} {name}' Save: Tallenna - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Muokkaa SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: UnlinkSelfFailure: 'Et voi siirtää itseäsi pois tästä ryhmästä: menettäisit pääkäyttäjän oikeudet' SilverStripe\Forms\GridField\GridFieldPaginator: OF: / Page: Sivu View: Näytä - SilverStripe\Forms\GridField\GridFieldVersionedState: - ADDEDTODRAFTHELP: 'Kohdetta ei ole julkaistu vielä' - ADDEDTODRAFTSHORT: Luonnos - ARCHIVEDPAGEHELP: 'Kohde on poistettu luonnoksista ja julkaisusta' - ARCHIVEDPAGESHORT: Arkistoitu - MODIFIEDONDRAFTHELP: 'Kohteella on julkaisemattomia muutoksia' - MODIFIEDONDRAFTSHORT: Muokattu - ONLIVEONLYSHORT: 'Vain julkaistuna' - ONLIVEONLYSHORTHELP: 'Kohde on julkaistu, mutta poistettu luonnoksista' SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Määrä FIELDLABELCURRENCY: Valuutta @@ -211,6 +197,7 @@ fi: many_many_Members: Jäsenet SilverStripe\Security\LoginAttempt: Email: Sähköpostiosoite + EmailHashed: 'Sähköpostiosoite (tiivistetty)' IP: IP-osoite PLURALNAME: Kirjautumisyritykset PLURALS: @@ -269,6 +256,8 @@ fi: SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: ERRORWRONGCRED: 'Antamasi tiedot eivät näytä oikeilta. Yritä uudelleen.' NoPassword: 'Tällä käyttäjällä ei ole salasanaa' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'Sähköpostiosoite & salasana' SilverStripe\Security\MemberPassword: PLURALNAME: 'Käyttäjän salasanat' PLURALS: @@ -330,7 +319,4 @@ fi: LOGOUT: 'Kirjaudu ulos' LOSTPASSWORDHEADER: 'Unohtunut salasana' NOTEPAGESECURED: 'Tämä sivu on suojattu. Syötä tunnistetietosi alle niin pääset eteenpäin.' - NOTERESETLINKINVALID: '

Salasanan palautuslinkki on virheellinen tai vanhentunut.

Voit pyytää uuden napsauttamalla tästä tai vaihtaa salasanasi kirjautumisen jälkeen.

' NOTERESETPASSWORD: 'Syötä sähköpostiosoitteesi ja lähetämme sinulle linkin, jonka avulla saat palautettua salasanasi' - PASSWORDSENTHEADER: 'Salasanan palautuslinkki lähetettiin osoitteeseen ''{email}''' - PASSWORDSENTTEXT: 'Kiitos! Salasanan palautuslinkki lähetettiin osoitteeseen ''{email}'', joka on liitettynä tähän käyttäjätiliin.' diff --git a/lang/fo.yml b/lang/fo.yml index b9f881ac6..e95dfc85c 100644 --- a/lang/fo.yml +++ b/lang/fo.yml @@ -1,9 +1,6 @@ fo: SilverStripe\Forms\ConfirmedPasswordField: SHOWONCLICKTITLE: 'Broyt loyniorð' - SilverStripe\Forms\DateField: - NOTSET: 'ikki ásett' - TODAY: 'í dag' SilverStripe\Forms\DropdownField: CHOOSE: (Áset) SilverStripe\Forms\Form: diff --git a/lang/fr.yml b/lang/fr.yml index c6f59e67f..450cfdb87 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -37,8 +37,6 @@ fr: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'non renseigné' - TODAY: 'aujourd''hui' VALIDDATEFORMAT2: 'Saisissez une date au format valide ({format})' VALIDDATEMAXDATE: 'La date doit être antérieure ou égale à celle autorisée ({date})' VALIDDATEMINDATE: 'La date doit être postérieure ou égale à celle autorisée ({date})' @@ -86,7 +84,6 @@ fr: RelationSearch: 'Rechercher relations' ResetFilter: Réinitialiser SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Supprimer Delete: Supprimer DeletePermissionsFailure: 'Vous n’avez pas les autorisations pour supprimer' EditPermissionsFailure: 'Pas de permissions pour délier l''enregistrement' @@ -98,23 +95,12 @@ fr: DeletePermissionsFailure: 'Vous n’avez pas les autorisations pour supprimer' Deleted: '{type} {name} supprimés' Save: Enregistrer - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Editer SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: UnlinkSelfFailure: 'Impossible de retirer votre propre profil de ce groupe, vous perdriez vos droits d''administration' SilverStripe\Forms\GridField\GridFieldPaginator: OF: de Page: Page View: Vue - SilverStripe\Forms\GridField\GridFieldVersionedState: - ADDEDTODRAFTHELP: 'L''élément n''a pas encore été publié' - ADDEDTODRAFTSHORT: Brouillon - ARCHIVEDPAGEHELP: 'Elément retiré du brouillon et du site public' - ARCHIVEDPAGESHORT: Archivé - MODIFIEDONDRAFTHELP: 'L''élément comporte des modifications non sauvegardées' - MODIFIEDONDRAFTSHORT: Modifié - ONLIVEONLYSHORT: 'Site public uniquement' - ONLIVEONLYSHORTHELP: 'L''élément a été publié, mais sa version brouillon a été supprimée' SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Quantité FIELDLABELCURRENCY: Devise @@ -211,6 +197,7 @@ fr: many_many_Members: Membres SilverStripe\Security\LoginAttempt: Email: 'Adresse email' + EmailHashed: 'Adresse Email (hashed)' IP: 'Adresse IP' PLURALNAME: 'Tentatives de connexion' PLURALS: @@ -269,6 +256,8 @@ fr: SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: ERRORWRONGCRED: 'Les renseignements fournis semblent incorrects. Merci de réessayer.' NoPassword: 'Ce membre n''a pas de mot de passe' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'Email & Mot de passe' SilverStripe\Security\MemberPassword: PLURALNAME: 'Mots de passe utilisateur' PLURALS: @@ -330,7 +319,4 @@ fr: LOGOUT: 'Se déconnecter' LOSTPASSWORDHEADER: 'Mot de passe oublié' NOTEPAGESECURED: 'Cette page est sécurisée. Entrez vos identifiants ci-dessous et vous pourrez y avoir accès.' - NOTERESETLINKINVALID: '

Le lien de réinitialisation du mot de passe n’est pas valide ou a expiré.

Vous pouvez en demander un nouveau en suivant ce lien ou changer de mot de passe après connexion.

' NOTERESETPASSWORD: 'Entrez votre adresse email et nous vous enverrons un lien pour modifier votre mot de passe' - PASSWORDSENTHEADER: "Lien de réinitialisation de mot de passe envoyé à «\_{email}\_»" - PASSWORDSENTTEXT: "Merci\_! Un lien de réinitialisation vient d’être envoyé à «\_{email}\_», à condition que cette adresse existe." diff --git a/lang/gl_ES.yml b/lang/gl_ES.yml index c165b63a1..b9773f123 100644 --- a/lang/gl_ES.yml +++ b/lang/gl_ES.yml @@ -3,8 +3,6 @@ gl_ES: SHOWONCLICKTITLE: 'Mudar Contrasinal' SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: € - SilverStripe\Forms\DateField: - NOTSET: 'sen establecer' SilverStripe\Forms\DropdownField: CHOOSE: (Escoller) SilverStripe\Forms\Form: diff --git a/lang/hr.yml b/lang/hr.yml index c0823ee2b..f7087f039 100644 --- a/lang/hr.yml +++ b/lang/hr.yml @@ -7,8 +7,6 @@ hr: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'nije postavljeno' - TODAY: danas VALIDDATEFORMAT2: 'Molimo unesite datum u ispravnom formatu ({format})' SilverStripe\Forms\DropdownField: CHOOSE: (Odaberite) @@ -26,7 +24,6 @@ hr: Find: Pronađi Print: Ispiši SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Obriši Delete: Obriši SilverStripe\Forms\GridField\GridFieldDetailForm: CancelBtn: Odustani @@ -35,8 +32,6 @@ hr: DeletePermissionsFailure: 'Nema dozvole brisanja' Deleted: 'Obrisano {type} {name}' Save: Spremi - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Uredi SilverStripe\Forms\MoneyField: FIELDLABELCURRENCY: Valuta SilverStripe\ORM\FieldType\DBBoolean: diff --git a/lang/id.yml b/lang/id.yml index 4e8bf8875..c9c06bbff 100644 --- a/lang/id.yml +++ b/lang/id.yml @@ -10,8 +10,6 @@ id: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'tidak diatur' - TODAY: 'hari ini' VALIDDATEFORMAT2: 'Mohon isikan format tanggal yang valid ({format})' VALIDDATEMAXDATE: 'Tanggal Anda harus lebih lama atau sama dengan tanggal maksimum ({date})' VALIDDATEMINDATE: 'Tanggal Anda harus lebih baru atau sama dengan tanggal minimum ({date})' @@ -47,7 +45,6 @@ id: RelationSearch: 'Cari yang terkait' ResetFilter: Reset SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Hapus Delete: Hapus DeletePermissionsFailure: 'Tidak ada ijin menghapus' EditPermissionsFailure: 'Tidak ada ijin membuka tautan' @@ -59,8 +56,6 @@ id: DeletePermissionsFailure: 'Tidak ada ijin menghapus' Deleted: '{type} {name} dihapus' Save: Simpan - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Edit SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Jumlah FIELDLABELCURRENCY: 'Mata Uang' @@ -172,7 +167,4 @@ id: LOGIN: Masuk LOSTPASSWORDHEADER: 'Kata Kunci yang Terlupa' NOTEPAGESECURED: 'Laman ini diamankan. Isikan data berikut untuk dikirimkan hak akses Anda.' - NOTERESETLINKINVALID: '

Tautan penggantian kata kunci tidak valid atau sudah kadaluarsa.

Anda dapat meminta yang baru di sini atau mengganti kata kunci setelah Anda masuk.

' NOTERESETPASSWORD: 'Isikan alamat email Anda untuk mendapatkan tautan penggantian kata kunci' - PASSWORDSENTHEADER: 'Tautan penggantian kata kunci dikirimkan ke ''{email}''' - PASSWORDSENTTEXT: 'Terimakasih! Tautan reset telah dikirim ke ''{email}'', berisi informasi akun untuk alamat email ini.' diff --git a/lang/id_ID.yml b/lang/id_ID.yml index 9d4b6a922..11d1f2bb3 100644 --- a/lang/id_ID.yml +++ b/lang/id_ID.yml @@ -10,8 +10,6 @@ id_ID: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'tidak diatur' - TODAY: 'hari ini' VALIDDATEFORMAT2: 'Mohon isikan format tanggal yang valid ({format})' VALIDDATEMAXDATE: 'Tanggal Anda harus lebih lama atau sama dengan tanggal maksimum ({date})' VALIDDATEMINDATE: 'Tanggal Anda harus lebih baru atau sama dengan tanggal minimum ({date})' @@ -47,7 +45,6 @@ id_ID: RelationSearch: 'Cari yang terkait' ResetFilter: Reset SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Hapus Delete: Hapus DeletePermissionsFailure: 'Tidak ada ijin menghapus' EditPermissionsFailure: 'Tidak ada ijin membuka tautan' @@ -59,8 +56,6 @@ id_ID: DeletePermissionsFailure: 'Tidak ada ijin menghapus' Deleted: '{type} {name} dihapus' Save: Simpan - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Edit SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Jumlah FIELDLABELCURRENCY: 'Mata Uang' @@ -171,7 +166,4 @@ id_ID: LOGIN: Masuk LOSTPASSWORDHEADER: 'Kata Kunci yang Terlupa' NOTEPAGESECURED: 'Laman ini diamankan. Isikan data berikut untuk dikirimkan hak akses Anda.' - NOTERESETLINKINVALID: '

Tautan penggantian kata kunci tidak valid atau sudah kadaluarsa.

Anda dapat meminta yang baru di sini atau mengganti kata kunci setelah Anda masuk.

' NOTERESETPASSWORD: 'Isikan alamat email Anda untuk mendapatkan tautan penggantian kata kunci' - PASSWORDSENTHEADER: 'Tautan penggantian kata kunci dikirimkan ke ''{email}''' - PASSWORDSENTTEXT: 'Terimakasih! Tautan reset telah dikirim ke ''{email}'', berisi informasi akun untuk alamat email ini.' diff --git a/lang/is.yml b/lang/is.yml index 9da7485ab..dd322dfa5 100644 --- a/lang/is.yml +++ b/lang/is.yml @@ -3,9 +3,6 @@ is: SHOWONCLICKTITLE: 'Breyta lykliorði' SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: kr - SilverStripe\Forms\DateField: - NOTSET: 'ekki valið' - TODAY: 'í dag' SilverStripe\Forms\DropdownField: CHOOSE: (Veldu) SilverStripe\Forms\Form: diff --git a/lang/it.yml b/lang/it.yml index dddfb094a..adbdeb0fd 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -37,8 +37,6 @@ it: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'non impostato' - TODAY: oggi VALIDDATEFORMAT2: 'Inserisci un formato di data valido ({format})' VALIDDATEMAXDATE: 'La tua data deve essere più vecchia o uguale alla data massima consentita ({date})' VALIDDATEMINDATE: 'La tua data deve essere più nuova o uguale alla data minima consentita ({date})' @@ -86,7 +84,6 @@ it: RelationSearch: 'Cerca relazione' ResetFilter: Azzera SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Elimina Delete: Elimina DeletePermissionsFailure: 'Non hai i permessi per eliminare' EditPermissionsFailure: 'Non hai i permessi per modificare' @@ -98,21 +95,12 @@ it: DeletePermissionsFailure: 'Non hai i permessi per eliminare' Deleted: 'Eliminato {type} {name}' Save: Salva - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Modifica + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Non è possibile rimuovere te stesso da questo gruppo, perderesti i diritti di admin' SilverStripe\Forms\GridField\GridFieldPaginator: OF: di Page: Pagina View: Visualizza - SilverStripe\Forms\GridField\GridFieldVersionedState: - ADDEDTODRAFTHELP: 'L''elemento non è stato ancora pubblicato' - ADDEDTODRAFTSHORT: Bozza - ARCHIVEDPAGEHELP: 'Elemento rimosso da bozza e live' - ARCHIVEDPAGESHORT: Archiviato - MODIFIEDONDRAFTHELP: 'L''elemento ha modifiche nascoste' - MODIFIEDONDRAFTSHORT: Modificato - ONLIVEONLYSHORT: 'Solo su live' - ONLIVEONLYSHORTHELP: 'L''elemento è pubblicato, ma è stato eliminato dal sito bozza' SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Importo FIELDLABELCURRENCY: Valuta @@ -209,6 +197,7 @@ it: many_many_Members: Membri SilverStripe\Security\LoginAttempt: Email: 'Indirizzo e-mail' + EmailHashed: 'Indirizzo email (hash)' IP: 'Indirizzo IP' PLURALNAME: 'Tentativi d''accesso' PLURALS: @@ -250,6 +239,7 @@ it: SUBJECTPASSWORDCHANGED: 'La tua password è stata cambiata' SUBJECTPASSWORDRESET: 'Link per azzerare la tua password' SURNAME: Cognome + VALIDATIONADMINLOSTACCESS: 'Non è possibile rimuovere tutti i gruppi admin dal tuo profilo' ValidationIdentifierFailed: 'Non posso sovrascrivere l''utente esistente #{id} con identificatore identico ({name} = {value}))' WELCOMEBACK: 'Bentornato, {firstname}' YOUROLDPASSWORD: 'La tua vecchia password' @@ -266,6 +256,8 @@ it: SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: ERRORWRONGCRED: 'I dettagli forniti non sembrano corretti. Per favore riprovare.' NoPassword: 'Manca la password per questo utente.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'E-mail & Password' SilverStripe\Security\MemberPassword: PLURALNAME: 'Password utenti' PLURALS: @@ -327,7 +319,4 @@ it: LOGOUT: Scollegati LOSTPASSWORDHEADER: 'Password smarrita' NOTEPAGESECURED: 'La pagina è protetta. Inserisci le credenziali qui sotto per poter andare avanti.' - NOTERESETLINKINVALID: '

Il link per azzerare la password non è valido o è scaduto.

Puoi richiederne uno nuovo qui o cambiare la tua password dopo che ti sei connesso.

' NOTERESETPASSWORD: 'Inserisci il tuo indirizzo e-mail e ti verrà inviato un link per poter azzerare la tua password.' - PASSWORDSENTHEADER: 'Link per azzeramento della password inviato a ''{email}''' - PASSWORDSENTTEXT: 'Grazie! Un link di azzeramento è stato inviato a ''{email}'', fornito un account esistente per questo indirizzo e-mail.' diff --git a/lang/ja.yml b/lang/ja.yml index 7f76ad481..433a832e2 100644 --- a/lang/ja.yml +++ b/lang/ja.yml @@ -5,8 +5,6 @@ ja: MAXIMUM: 'パスワードは{max} 文字以内でなければなりません。' SHOWONCLICKTITLE: パスワード変更 SilverStripe\Forms\DateField: - NOTSET: セットされていません - TODAY: 今日 VALIDDATEFORMAT2: '{{format}}日付フォーマットの正しい日付を入力してください。' VALIDDATEMAXDATE: '許可されている最も新しい日付{{date}}より古い日付か同じ日付である必要があります。' VALIDDATEMINDATE: '許可されている最も古い日付{{date}}より新しい日付か同じ日付である必要があります' @@ -39,7 +37,6 @@ ja: RelationSearch: 関連検索 ResetFilter: リセット SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: 削除 Delete: 削除 DeletePermissionsFailure: 削除権限がありません EditPermissionsFailure: レコードのリンクを解除するための権限がありません @@ -51,8 +48,6 @@ ja: DeletePermissionsFailure: 削除権限がありません Deleted: '削除済み {type} {name}' Save: 保存 - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: 編集 SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: 総計 FIELDLABELCURRENCY: 通貨 @@ -151,7 +146,4 @@ ja: ERRORPASSWORDPERMISSION: パスワードを変更する為に、ログインしなければなりません! LOGIN: ログイン NOTEPAGESECURED: このページはセキュリティで保護されております証明書キーを下記に入力してください。こちらからすぐに送信します - NOTERESETLINKINVALID: '

パスワードのリセットリンクは有効でないか期限切れです。

新しいパスワードを要求することができます ここ もしくはパスワードを変更することができます ログインした後 .

' NOTERESETPASSWORD: メールアドレスを入力してください、パスワードをリセットするURLを送信致します - PASSWORDSENTHEADER: 'パスワードリセットリンクは ''{email}'' に送信されました' - PASSWORDSENTTEXT: 'ありがとうございました! リセットリンクは、''{email}'' に、このアカウントが存在することを前提として送信されました。' diff --git a/lang/lt.yml b/lang/lt.yml index 5f70dd239..3ca7adbff 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -10,8 +10,6 @@ lt: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: € SilverStripe\Forms\DateField: - NOTSET: nenustatyta - TODAY: šiandien VALIDDATEFORMAT2: 'Prašome suvesti datą reikiamu formatu ({format})' VALIDDATEMAXDATE: 'Data privalo būti senesnė arba lygi vėliausiai galimai datai ({date})' VALIDDATEMINDATE: 'Data privalo būti naujesnė arba lygi anksčiausiai galimai datai ({date})' @@ -47,7 +45,6 @@ lt: RelationSearch: 'Sąryšių paieška' ResetFilter: Atstatyti SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Ištrinti Delete: Ištrinti DeletePermissionsFailure: 'Nėra leidimų trynimui' EditPermissionsFailure: 'Nėra leidimų atjungti įrašą' @@ -59,8 +56,6 @@ lt: DeletePermissionsFailure: 'Nėra leidimų trynimui' Deleted: 'Ištrinta {type} {name}' Save: Išsaugoti - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Redaguoti SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Kiekis FIELDLABELCURRENCY: Valiuta @@ -172,7 +167,4 @@ lt: LOGIN: Prisijungti LOSTPASSWORDHEADER: 'Slaptažodžio atstatymas' NOTEPAGESECURED: 'Šis puslapis yra apsaugotas. Įveskite savo duomenis į žemiau esančius laukelius.' - NOTERESETLINKINVALID: '

Neteisinga arba negaliojanti slaptažodžio atstatymo nuoroda.

Galite atsisiųsti naują čia arba pasikeisti slaptažodį po to, kai prisijungsite.

' NOTERESETPASSWORD: 'Įveskite savo e. pašto adresą ir atsiųsime slaptažodžio atstatymui skirtą nuorodą' - PASSWORDSENTHEADER: 'Slaptažodžio atstatymo nuoroda nusiųsta į ''{email}''' - PASSWORDSENTTEXT: 'Atstatymo nuoroda nusiųsta į ''{email}''' diff --git a/lang/lv.yml b/lang/lv.yml index d7106a435..cfa2299d9 100644 --- a/lang/lv.yml +++ b/lang/lv.yml @@ -3,9 +3,6 @@ lv: SHOWONCLICKTITLE: 'Mainīt paroli' SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: Ls - SilverStripe\Forms\DateField: - NOTSET: 'nav uzstādīts' - TODAY: šodien SilverStripe\Forms\DropdownField: CHOOSE: (Izvēlieties) SilverStripe\Forms\Form: diff --git a/lang/mi.yml b/lang/mi.yml index 954732f27..e9fe2308e 100644 --- a/lang/mi.yml +++ b/lang/mi.yml @@ -7,8 +7,6 @@ mi: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'kāore i tautuhia' - TODAY: 'tēnei rā' VALIDDATEFORMAT2: 'Tāurua he hōputu rā tika ({format})' VALIDDATEMAXDATE: 'Me tawhito ake tō rā, kia ōrite rānei ki te rā mōrahi ({date}) kua whakaaetia' VALIDDATEMINDATE: 'Me hōu ake tō rā, kia ōrite rānei ki te rā moroiti ({date}) kua whakaaetia' @@ -41,7 +39,6 @@ mi: RelationSearch: 'Rapu whanaunga' ResetFilter: 'Tautuhi anō' SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Muku Delete: Muku DeletePermissionsFailure: 'Kāore he muku whakaaetanga' EditPermissionsFailure: 'Kāore ō whakaaetanga kia wetehono pūkete' @@ -53,8 +50,6 @@ mi: DeletePermissionsFailure: 'Kāore he whakaaetanga muku' Deleted: 'Kua mukua {type} {name}' Save: Tiaki - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Whakatika SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Rahinga FIELDLABELCURRENCY: Moni @@ -154,7 +149,4 @@ mi: LOGIN: Takiuru LOSTPASSWORDHEADER: 'Kupuhipa Ngaro' NOTEPAGESECURED: 'Kua ngita tēnā whārangi. Tāurua ō taipitoptio tuakiri ki raro, ā, mā mātou koe e tuku kia haere tonu.' - NOTERESETLINKINVALID: '

He muhu, kua mōnehu rānei te hono tautuhi kupuhipa anō.

Ka taea te tono i te mea hōui konei ka huri rānei i tō kupuhipa ā muri i tōtakiuru.

' NOTERESETPASSWORD: 'Tāurua tō wāhitau īmēra, mā mātou e tuku tētahi hono ki a koe e taea ai te tautuhi anō i tō kupuhipa' - PASSWORDSENTHEADER: 'I tukuna he hono tautuhi kupuhipa anō ki ''{email}''' - PASSWORDSENTTEXT: 'Kia ora! Kua tukuna he hono tautuhi anō ki ''{email}'',engari rā kei te tīariari he pūkete mō taua wāhitau īmēra.' diff --git a/lang/nb.yml b/lang/nb.yml index 2825f7543..f1dc4c74d 100644 --- a/lang/nb.yml +++ b/lang/nb.yml @@ -7,8 +7,6 @@ nb: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'Ikke satt' - TODAY: 'i dag' VALIDDATEFORMAT2: 'Vennligst skriv inn et gyldig datoformat ({format})' VALIDDATEMAXDATE: 'Din dato må være eldre eller i samsvar med maksimum tillatte dato ({date})' VALIDDATEMINDATE: 'Din dato må være nyere eller i samsvar med minimum tillatte dato ({date})' @@ -41,7 +39,6 @@ nb: RelationSearch: Relasjonssøk ResetFilter: Tilbakestille SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Slett Delete: Slett DeletePermissionsFailure: 'Ikke tillatt å slette' EditPermissionsFailure: 'Ikke tilgang til å fjerne oppføringer' @@ -53,8 +50,6 @@ nb: DeletePermissionsFailure: 'Ikke tillatt å slette' Deleted: 'Slettet {type} {name}' Save: Lagre - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Rediger SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Mengde FIELDLABELCURRENCY: Valuta @@ -157,7 +152,4 @@ nb: LOGIN: 'Logg inn' LOSTPASSWORDHEADER: 'Mistet passord' NOTEPAGESECURED: 'Den siden er sikret. Skriv inn gyldig innloggingsinfo så kommer du inn.' - NOTERESETLINKINVALID: '

Lenken for å nullstille passordet er ugyldig eller utgått.

Du kan kreve en ny her eller endre passordet etter at du har logget inn.

' NOTERESETPASSWORD: 'Skriv inn epostadressen din og vi vil sende deg en lenke som nullstiller passordet.' - PASSWORDSENTHEADER: 'Lenke for nullstilling av passord ble sendt til ''{email}''' - PASSWORDSENTTEXT: 'Takk! En lenke for å lage nytt passord er sendt til ''{email}'', forutsatt at det eksisterer en konto for denne epostadressen.' diff --git a/lang/nl.yml b/lang/nl.yml index 2903dff05..f4e35af66 100644 --- a/lang/nl.yml +++ b/lang/nl.yml @@ -1,4 +1,26 @@ nl: + SilverStripe\Admin\LeftAndMain: + VersionUnknown: onbekend + SilverStripe\AssetAdmin\Forms\UploadField: + Dimensions: Afmetingen + EDIT: Bewerken + EDITINFO: 'Bewerk dit bestand' + REMOVE: Verwijder + SilverStripe\Control\ChangePasswordEmail_ss: + CHANGEPASSWORDFOREMAIL: 'Het wachtwoord voor het account met e-mailadres {email} is aangepast. Indien u uw wachtwoord niet heeft aangepast kunt u dat doen met onderstaande link.' + CHANGEPASSWORDTEXT1: 'U heeft het wachtwoord veranderd voor' + CHANGEPASSWORDTEXT3: 'Wachtwoord veranderen' + HELLO: Hallo + SilverStripe\Control\Email\ForgotPasswordEmail_ss: + HELLO: Hallo + TEXT1: 'Hier is uw' + TEXT2: 'link om uw wachtwoord opnieuw aan te maken' + TEXT3: voor + SilverStripe\Control\RequestProcessor: + INVALID_REQUEST: 'Fout bij verwerken' + REQUEST_ABORTED: 'Fout bij verwerken (geannuleerd)' + SilverStripe\Core\Manifest\VersionProvider: + VERSIONUNKNOWN: Onbekend SilverStripe\Forms\CheckboxField: NOANSWER: Nee YESANSWER: Ja @@ -8,22 +30,30 @@ nl: ATLEAST: 'Een wachtwoord moet tenminste {min} karakters hebben.' BETWEEN: 'Een wachtwoord moet tussen de {min} en {max} karakters hebben' CURRENT_PASSWORD_ERROR: 'Het wachtwoord dat u heeft ingevoerd is niet juist.' + CURRENT_PASSWORD_MISSING: 'Voer uw huidige wachtwoord in.' + LOGGED_IN_ERROR: 'U moet ingelogd zijn om uw wachtwoord te kunnen veranderen!' MAXIMUM: 'Een wachtwoord mag maximaal {max} karakters hebben.' SHOWONCLICKTITLE: 'Verander wachtwoord' SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'niet ingesteld' - TODAY: vandaag VALIDDATEFORMAT2: 'Vul een geldig datumformaat in ({format})' VALIDDATEMAXDATE: 'De datum moet ouder of gelijk zijn aan de maximale datum ({date})' VALIDDATEMINDATE: 'De datum moet nieuwer of gelijk zijn aan de minimale datum ({date})' + SilverStripe\Forms\DatetimeField: + VALIDDATEMAXDATETIME: 'De datum moet ouder of gelijk zijn aan de maximale datum ({datetime})' + VALIDDATETIMEFORMAT: 'Vul een geldige datum in ({format})' + VALIDDATETIMEMINDATE: 'De datum moet nieuwer of gelijk zijn aan de minimale datum ({datetime})' SilverStripe\Forms\DropdownField: CHOOSE: (Kies) + CHOOSE_MODEL: '(Selecteer {name})' SOURCE_VALIDATION: 'Selecteer een optie uit de lijst. {value} is geen geldige keuze.' SilverStripe\Forms\EmailField: VALIDATION: 'Gelieve een e-mailadres in te voeren.' + SilverStripe\Forms\FileUploadReceiver: + FIELDNOTSET: 'Bestandsinformatie niet gevonden' SilverStripe\Forms\Form: + BAD_METHOD: 'Dit formulier moet middels {method} verzonden worden' CSRF_EXPIRED_MESSAGE: 'Uw sessie is verlopen. Verzend het formulier opnieuw.' CSRF_FAILED_MESSAGE: 'Er lijkt een technisch probleem te zijn. Klik op de knop terug, vernieuw uw browser, en probeer het opnieuw.' VALIDATIONPASSWORDSDONTMATCH: 'Wachtwoorden komen niet overeen' @@ -32,7 +62,10 @@ nl: VALIDATOR: Validator VALIDCURRENCY: 'Vul een geldige munteenheid in' SilverStripe\Forms\FormField: + EXAMPLE: 'bijv. {format}' NONE: geen + SilverStripe\Forms\FormScaffolder: + TABMAIN: Hoofdgedeelte SilverStripe\Forms\GridField\GridField: Add: '{name} toevoegen' CSVEXPORT: 'Exporteer naar CSV' @@ -51,7 +84,6 @@ nl: RelationSearch: 'Zoek relatie' ResetFilter: Resetten SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Verwijderen Delete: Verwijder DeletePermissionsFailure: 'Onvoldoende rechten om te verwijderen' EditPermissionsFailure: 'Geen toelating om te ontkoppelen' @@ -63,29 +95,63 @@ nl: DeletePermissionsFailure: 'Onvoldoende rechten om te verwijderen' Deleted: '{type} {name} verwijderd' Save: Opslaan - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Bewerken + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'U kunt uzelf niet verwijderen van deze groep, omdat u dan geen admin-rechten meer heeft.' + SilverStripe\Forms\GridField\GridFieldPaginator: + OF: van + Page: Pagina + View: Bekijk SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Aantal FIELDLABELCURRENCY: Munteenheid + INVALID_CURRENCY: 'Valuta {currency} is niet toegestaan' + SilverStripe\Forms\MultiSelectField: + SOURCE_VALIDATION: 'Selecteer een optie uit de lijst. {value} is geen geldige keuze.' SilverStripe\Forms\NullableField: IsNullLabel: 'Is null' SilverStripe\Forms\NumericField: VALIDATION: '''{value}'' is geen getal, enkel getallen worden door dit veld geaccepteerd' SilverStripe\Forms\TimeField: VALIDATEFORMAT: 'Vul een geldig datumformaat in ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: 'Data objecten' + PLURALS: + one: 'Data object' + other: '{count} Data objecten' + SINGULARNAME: 'Data object' SilverStripe\ORM\FieldType\DBBoolean: ANY: Elke NOANSWER: Nee YESANSWER: Ja SilverStripe\ORM\FieldType\DBDate: + DAYS_SHORT_PLURALS: + one: '{count} dag' + other: '{count} dagen' + HOURS_SHORT_PLURALS: + one: '{count} uur' + other: '{count} uren' LessThanMinuteAgo: 'minder dan één minuut' + MINUTES_SHORT_PLURALS: + one: '{count} minuut' + other: '{count} minuten' + MONTHS_SHORT_PLURALS: + one: '{count} maand' + other: '{count} maanden' + SECONDS_SHORT_PLURALS: + one: '{count} seconde' + other: '{count} seconden' TIMEDIFFAGO: '{difference} geleden' TIMEDIFFIN: 'in {difference}' + YEARS_SHORT_PLURALS: + one: '{count} jaar' + other: '{count} jaren' SilverStripe\ORM\FieldType\DBEnum: ANY: Elke + SilverStripe\ORM\Hierarchy: + LIMITED_TITLE: 'Teveel onderliggende items ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: InfiniteLoopNotAllowed: 'Oneindige lus gevonden in "{type}" hiërarchie. Wijzig het hogere niveau om dit op te lossen' + LIMITED_TITLE: 'Teveel onderliggende items ({count})' SilverStripe\ORM\ValidationException: DEFAULT_ERROR: Validatiefout SilverStripe\Security\BasicAuth: @@ -96,34 +162,60 @@ nl: PASSWORDEXPIRED: '

Uw wachtwoord is verlopen. Kies een nieuw wachtwoord.

' SilverStripe\Security\CMSSecurity: INVALIDUSER: '

Ongeldige gebruiker Log hier opnieuw in om verder te gaan.

' + LOGIN_MESSAGE: 'Sessie is verlopen' + LOGIN_TITLE: '

U kunt verder met wat u aan het doen was, door opnieuw in te loggen.

' SUCCESS: Succes SUCCESSCONTENT: '

U bent ingelogd. Klik hier als u niet automatisch wordt doorgestuurd.

' + SUCCESS_TITLE: 'Inloggen is gelukt' + SilverStripe\Security\DefaultAdminService: + DefaultAdminFirstname: 'Standaard Beheerder' SilverStripe\Security\Group: AddRole: 'Voeg een rol toe aan deze groep' Code: 'Groep code' DefaultGroupTitleAdministrators: Beheerders DefaultGroupTitleContentAuthors: 'Inhoud Auteurs' Description: 'Omschrijving ' + GROUPNAME: 'Groep naam' GroupReminder: 'Als u de bovenliggende groep selecteert, neemt deze groep alle rollen over' HierarchyPermsError: 'U moet (ADMIN) rechten hebben om de bovenliggende groep "{group}" toe te kennen' Locked: 'Gesloten?' + MEMBERS: Leden + NEWGROUP: 'Nieuwe groep' NoRoles: 'Geen rollen gevonden' + PERMISSIONS: Rechten + PLURALNAME: Groepen + PLURALS: + one: 'Een groep' + other: '{count} groepen' Parent: 'Bovenliggende groep' + ROLES: Rollen + ROLESDESCRIPTION: 'Rollen zijn logische groeperingen van rechten die in het Rollen tabblad gewijzigd kunnen worden.
Rollen worden automatisch overgenomen van bovenliggende groepen.' RolesAddEditLink: 'Rollen beheren' + SINGULARNAME: Groep Sort: Sorteer-richting has_many_Permissions: Rechten many_many_Members: Leden SilverStripe\Security\LoginAttempt: + Email: 'E-mailadres ' + EmailHashed: 'E-mailadres (versleuteld)' IP: 'IP adres' + PLURALNAME: Inlogpogingen + PLURALS: + one: 'Een inlogpoging' + other: '{count} inlogpogingen' + SINGULARNAME: Inlogpogingen Status: Status SilverStripe\Security\Member: ADDGROUP: 'Groep toevoegen' BUTTONCHANGEPASSWORD: 'Wachtwoord veranderen' BUTTONLOGIN: Inloggen BUTTONLOGINOTHER: 'Als iemand anders inloggen' + BUTTONLOGOUT: Uitloggen BUTTONLOSTPASSWORD: 'Ik ben mijn wachtwoord vergeten' CONFIRMNEWPASSWORD: 'Bevestig het nieuwe wachtwoord' CONFIRMPASSWORD: 'Bevestig wachtwoord' + CURRENT_PASSWORD: 'Huidige wachtwoord' + EDIT_PASSWORD: 'Nieuw wachtwoord' EMAIL: E-mail EMPTYNEWPASSWORD: 'Het nieuwe wachtwoord mag niet leeg zijn, probeer opnieuw' ENTEREMAIL: 'Typ uw e-mailadres om een link te ontvangen waarmee u uw wachtwoord kunt resetten.' @@ -133,13 +225,21 @@ nl: ERRORWRONGCRED: 'De ingevulde gegevens lijken niet correct. Probeer het nog een keer.' FIRSTNAME: Voornaam INTERFACELANG: 'Interface taal' + KEEPMESIGNEDIN: 'Houd mij ingelogd' LOGGEDINAS: 'U bent ingelogd als {name}.' NEWPASSWORD: 'Nieuw wachtwoord' PASSWORD: Wachtwoord PASSWORDEXPIRED: 'Uw wachtwoord is verlopen. Kies een nieuw wachtwoord.' + PLURALNAME: Leden + PLURALS: + one: 'Een lid' + other: '{count} leden' + REMEMBERME: 'Onthoud mij voor volgende keer? (voor {count} dagen op dit apparaat)' + SINGULARNAME: Lid SUBJECTPASSWORDCHANGED: 'Uw wachtwoord is veranderd' SUBJECTPASSWORDRESET: 'Link om uw wachtwoord opnieuw aan te maken' SURNAME: Achternaam + VALIDATIONADMINLOSTACCESS: 'Niet mogelijk om alle admin-groepen te verwijderen van uw profiel' ValidationIdentifierFailed: 'Een bestaande gebruiker #{id} kan niet dezelfde unieke velden hebben ({name} = {value}))' WELCOMEBACK: 'Welkom terug, {firstname}' YOUROLDPASSWORD: 'Uw oude wachtwoord' @@ -148,15 +248,38 @@ nl: db_LockedOutUntil: 'Gesloten tot' db_Password: Wachtwoord db_PasswordExpiry: 'Wachtwoord vervaldatum' + SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: + AUTHENTICATORNAME: Inlogformulier + BUTTONFORGOTPASSWORD: 'Wachtwoord vergeten' + BUTTONLOGIN: 'Opnieuw inloggen' + BUTTONLOGOUT: Uitloggen + SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: + ERRORWRONGCRED: 'De ingevulde gegevens lijken niet correct. Probeer het nog een keer.' + NoPassword: 'Er is geen wachtwoord voor deze gebruiker.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'E-mail & wachtwoord' + SilverStripe\Security\MemberPassword: + PLURALNAME: Gebruikerswachtwoorden + PLURALS: + one: 'Een gebruikerswachtwoord' + other: '{count} Gebruikerswachtwoorden' + SINGULARNAME: Gebruikerswachtwoord SilverStripe\Security\PasswordValidator: LOWCHARSTRENGTH: 'Maak a.u.b. uw wachtwoord sterker door enkele van de volgende karakters te gebruiken: {chars}' PREVPASSWORD: 'U heeft dit wachtwoord in het verleden al gebruikt, kies a.u.b. een nieuw wachtwoord.' TOOSHORT: 'Het wachtwoord is te kort, het moet minimaal {minimum} karakters hebben' SilverStripe\Security\Permission: AdminGroup: Beheerder + CMS_ACCESS_CATEGORY: 'CMS toegang' CONTENT_CATEGORY: Inhoudsrechten FULLADMINRIGHTS: 'Volledige admin rechten' FULLADMINRIGHTS_HELP: 'Impliceert en overstemt alle andere toegewezen rechten.' + PERMISSIONS_CATEGORY: 'Rollen en toegangsrechten' + PLURALNAME: Rechten + PLURALS: + one: Machtiging + other: '{count} rechten' + SINGULARNAME: Machtiging UserPermissionsIntro: 'Groepen aan deze gebruiker toewijzen zullen diens permissies aanpassen. Zie de sectie Groepen voor meer informatie over machtigingen voor afzonderlijke groepen.' SilverStripe\Security\PermissionCheckboxSetField: AssignedTo: 'toegewezen aan "{title}"' @@ -166,21 +289,34 @@ nl: SilverStripe\Security\PermissionRole: OnlyAdminCanApply: 'Alleen admin kan doorvoeren' PLURALNAME: Rollen + PLURALS: + one: 'Een rol' + other: '{count} rollen' SINGULARNAME: Rol Title: Titel SilverStripe\Security\PermissionRoleCode: + PLURALNAME: 'Permissie codes' + PLURALS: + one: 'Een permissiecode' + other: '{count} permissiecodes' PermsError: 'U moet (ADMIN) rechten hebben om de code "{code}" toe te kennen' + SINGULARNAME: Permissiecode + SilverStripe\Security\RememberLoginHash: + PLURALNAME: 'Versleutelde logins' + PLURALS: + one: 'Een versleutelde login' + other: '{count} versleutelde logins' + SINGULARNAME: 'Versleutelde login' SilverStripe\Security\Security: ALREADYLOGGEDIN: 'U hebt geen toegang tot deze pagina. Als u een andere account met de nodige rechten hebt, kan u hieronder opnieuw inloggen.' BUTTONSEND: 'Nieuw wachtwoord aanmaken' CHANGEPASSWORDBELOW: 'U kunt uw wachtwoord hieronder veranderen.' CHANGEPASSWORDHEADER: 'Verander uw wachtwoord' + CONFIRMLOGOUT: 'Klik op onderstaande knop om uit te loggen.' ENTERNEWPASSWORD: 'Voer een nieuw wachtwoord in.' ERRORPASSWORDPERMISSION: 'U moet ingelogd zijn om uw wachtwoord te kunnen veranderen!' LOGIN: 'Meld aan' + LOGOUT: Uitloggen LOSTPASSWORDHEADER: 'Wachtwoord vergeten' NOTEPAGESECURED: 'Deze pagina is beveiligd. Voer uw gegevens in en u wordt automatisch doorgestuurd.' - NOTERESETLINKINVALID: '

De link om uw wachtwoord te kunnen wijzigen is niet meer geldig.

U kunt een nieuwe link aanvragen of uw wachtwoord aanpassen door in te loggen.

' NOTERESETPASSWORD: 'Voer uw e-mailadres in en we sturen een link waarmee u een nieuw wachtwoord kunt instellen.' - PASSWORDSENTHEADER: 'Wachtwoord herstel link verzonden naar {email}' - PASSWORDSENTTEXT: 'Bedankt! Er is een link verstuurd naar {email} om uw wachtwoord opnieuw in te stellen, in de veronderstelling dat er een account bestaat voor dit e-mailadres.' diff --git a/lang/pl.yml b/lang/pl.yml index 03753f33b..1905acb38 100644 --- a/lang/pl.yml +++ b/lang/pl.yml @@ -1,34 +1,77 @@ pl: + SilverStripe\Admin\LeftAndMain: + VersionUnknown: Nieznany + SilverStripe\AssetAdmin\Forms\UploadField: + Dimensions: Rozmiar + EDIT: Edytuj + EDITINFO: 'Edytuj plik' + REMOVE: Usuń + SilverStripe\Control\ChangePasswordEmail_ss: + CHANGEPASSWORDFOREMAIL: 'Hasło do konta o adresie e-mail {email} zostało zmienione. Jeśli nie zmieniłeś swojego hasła, zmień hasło, korzystając z poniższego linku' + CHANGEPASSWORDTEXT1: 'Zmieniłeś hasło na' + CHANGEPASSWORDTEXT3: 'Zmień hasło' + HELLO: 'Witaj,' + SilverStripe\Control\Email\ForgotPasswordEmail_ss: + HELLO: 'Witaj,' + TEXT1: 'Oto twój' + TEXT2: 'link zmiany hasła' + TEXT3: dla + SilverStripe\Control\RequestProcessor: + INVALID_REQUEST: 'Nieprawidłowe żądanie' + REQUEST_ABORTED: 'Żądanie zostało przerwane' + SilverStripe\Core\Manifest\VersionProvider: + VERSIONUNKNOWN: Nieznany + SilverStripe\Forms\CheckboxField: + NOANSWER: Nie + YESANSWER: Tak + SilverStripe\Forms\CheckboxSetField_ss: + NOOPTIONSAVAILABLE: 'Brak dostępnych opcji' SilverStripe\Forms\ConfirmedPasswordField: ATLEAST: 'Hasła muszą mieć przynajmniej {min} znaków.' BETWEEN: 'Hasła muszą mieć długość pomiędzy {min} a {max} znaków.' + CURRENT_PASSWORD_ERROR: 'Podane hasło jest nieprawidłowe' + CURRENT_PASSWORD_MISSING: 'Musisz podać swoje aktualne hasło.' + LOGGED_IN_ERROR: 'Musisz być zalogowany aby zmienić hasło' MAXIMUM: 'Hasła mogą mieć co najwyżej {max} znaków.' SHOWONCLICKTITLE: 'Zmiana Hasła' SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'nie ustawiono' - TODAY: dzisiaj VALIDDATEFORMAT2: 'Proszę wprowadź prawidłowy format daty ({format})' VALIDDATEMAXDATE: 'Twoja data musi być wcześniejsza lub taka sama, jak maksymalna dozwolona data ({date})' VALIDDATEMINDATE: 'Twoja data musi być późniejsza lub taka sama, jak minimalna dozwolona data ({date})' + SilverStripe\Forms\DatetimeField: + VALIDDATEMAXDATETIME: 'Twoja data musi być wcześniejsza lub taka sama, jak maksymalna dozwolona data ({date})' + VALIDDATETIMEFORMAT: 'Proszę wprowadź prawidłowy format czasu ({format})' + VALIDDATETIMEMINDATE: 'Twoja data musi być późniejsza lub taka sama, jak minimalna dozwolona data ({date})' SilverStripe\Forms\DropdownField: CHOOSE: (wybierz) + CHOOSE_MODEL: '(Wybierz {name})' + SOURCE_VALIDATION: 'Wybierz wartość z podanej listy. {value} nie jest poprawną opcją' SilverStripe\Forms\EmailField: VALIDATION: 'Proszę podaj adres e-mail' + SilverStripe\Forms\FileUploadReceiver: + FIELDNOTSET: 'Nie znaleziono informacji o pliku' SilverStripe\Forms\Form: + BAD_METHOD: 'Ten formularz wymaga {metody} przesłania' + CSRF_EXPIRED_MESSAGE: 'Twoja sesja wygasła. Prześlij ponownie formularz.' + CSRF_FAILED_MESSAGE: 'Wygląda na to, że wystąpił błąd techniczny. Kliknij przycisk wstecz, następnie odśwież przeglądarkę aby wczytać stronę ponownie.' VALIDATIONPASSWORDSDONTMATCH: 'Hasła nie są takie same' VALIDATIONPASSWORDSNOTEMPTY: 'Hasło nie może być puste' VALIDATIONSTRONGPASSWORD: 'Hasła muszą mieć przynajmniej jedną cyfrę oraz jeden znak alfanumeryczny.' VALIDATOR: Walidator VALIDCURRENCY: 'Proszę podaj prawidłową walutę' SilverStripe\Forms\FormField: + EXAMPLE: 'na przykład {format}' NONE: brak + SilverStripe\Forms\FormScaffolder: + TABMAIN: Główny SilverStripe\Forms\GridField\GridField: Add: 'Dodaj {name}' CSVEXPORT: 'Eksportuj do CSV' + CSVIMPORT: 'Import z CSV' Filter: Filtr - FilterBy: 'Filtruj wg' + FilterBy: 'Filtruj wg ' Find: Wyszukaj LinkExisting: 'Linkuj istniejący' NewRecord: 'Nowy {type}' @@ -41,7 +84,6 @@ pl: RelationSearch: 'Wyszukiwanie powiązań' ResetFilter: Resetuj SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Usuń Delete: Usuń DeletePermissionsFailure: 'Brak uprawnień do usuwania' EditPermissionsFailure: 'Nie masz uprawnień, aby odłączyć rekord' @@ -53,57 +95,145 @@ pl: DeletePermissionsFailure: 'Brak uprawnień do usuwania' Deleted: 'Usunięto {type} {name}' Save: Zapisz - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Edytuj + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Nie możesz usunąć siebie z tej grupy, stracone zostałby prawa administratora' + SilverStripe\Forms\GridField\GridFieldPaginator: + OF: z + Page: Strona + View: Widok SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Ilość FIELDLABELCURRENCY: waluta + INVALID_CURRENCY: 'Waluta {currency} nie znajduje się na liście dozwolonych walut' + SilverStripe\Forms\MultiSelectField: + SOURCE_VALIDATION: 'Wybierz wartości z podanej listy. Podano niepoprawną opcję {value}' SilverStripe\Forms\NullableField: IsNullLabel: 'Jest Pusty' SilverStripe\Forms\NumericField: VALIDATION: '''{value}'' nie jest liczbą, to pole przyjmuje tylko liczby' SilverStripe\Forms\TimeField: VALIDATEFORMAT: 'Proszę wprowadź prawidłowy format czasu ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: 'Obiekty danych' + PLURALS: + one: 'Obiekt danych' + few: 'Obiektów danych' + many: 'Obiektów danych' + other: 'Obiektów danych {count}' + SINGULARNAME: 'Obiekt danych' SilverStripe\ORM\FieldType\DBBoolean: ANY: Jakikolwiek + NOANSWER: Nie + YESANSWER: Tak SilverStripe\ORM\FieldType\DBDate: + DAYS_SHORT_PLURALS: + one: '{count} dzień' + few: '{count} dni' + many: '{count} dni' + other: '{count} dni' + HOURS_SHORT_PLURALS: + one: '{count} godzina' + few: '{count} godzin' + many: '{count} godzin' + other: '{count} godzin' LessThanMinuteAgo: 'mniej niż minuta' + MINUTES_SHORT_PLURALS: + one: '{count} minuta' + few: '{count} minut' + many: '{count} minut' + other: '{count} minut' + MONTHS_SHORT_PLURALS: + one: '{count} miesiąc' + few: '{count} miesięcy' + many: '{count} miesięcy' + other: '{count} miesięcy' + SECONDS_SHORT_PLURALS: + one: '{count} sekunda' + few: '{count} sekund' + many: '{count} sekund' + other: '{count} sekund' TIMEDIFFAGO: '{difference} temu' TIMEDIFFIN: 'w {difference}' + YEARS_SHORT_PLURALS: + one: '{count} rok' + few: '{count} lat' + many: '{count} lat' + other: '{count} lat' SilverStripe\ORM\FieldType\DBEnum: ANY: Jakikolwiek + SilverStripe\ORM\Hierarchy: + LIMITED_TITLE: 'Zbyt wiele dzieci ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: InfiniteLoopNotAllowed: 'Znaleziono nieskończoną pętlę wewnątrz hierarchii "{type}". Proszę zmień rodzica by to rozwiązać.' + LIMITED_TITLE: 'Zbyt wiele dzieci ({count})' + SilverStripe\ORM\ValidationException: + DEFAULT_ERROR: 'Niepoprawne dane' SilverStripe\Security\BasicAuth: ENTERINFO: 'Wprowadź username i hasło' ERRORNOTADMIN: 'Ten użytkownik nie jest administratorem' ERRORNOTREC: 'Nie istnieje taki username/hasło' + SilverStripe\Security\CMSMemberLoginForm: + PASSWORDEXPIRED: '

Twoje hasło wygasło. Prosimy wybrać nowe.

' + SilverStripe\Security\CMSSecurity: + INVALIDUSER: '

Niepoprawny użytkownik. Prosimy o ponownie uwierzytelnienie – aby kontynuować.

' + LOGIN_MESSAGE: '

Twoja sesja wygasła z powodu braku aktywności

' + LOGIN_TITLE: 'Wróć do strony, z którym połączenie zostało przerwane, logując się ponownie' + SUCCESS: Sukces + SUCCESSCONTENT: '

Zalogowano poprawnie! Jeżeli nie zostaniesz automatycznie przekierowany kliknij tutaj

' + SUCCESS_TITLE: 'Zalogowano poprawne' + SilverStripe\Security\DefaultAdminService: + DefaultAdminFirstname: 'Domyślny administrator' SilverStripe\Security\Group: AddRole: 'Dodaj rolę dla tej grupy' Code: 'Kod Grupy' DefaultGroupTitleAdministrators: Administratorzy DefaultGroupTitleContentAuthors: 'Autor treści' Description: Opis + GROUPNAME: 'Nazwa Grupy' GroupReminder: 'Jeśli wybierzesz nadrzędną grupę, obecna grupa otrzyma wszystkie jej role' HierarchyPermsError: 'Nie można przyporządkować uprzywilejowanej grupy "{group}" (wymagane uprawnienie ADMIN)' Locked: 'Zablokowana?' + MEMBERS: Użytkownicy + NEWGROUP: 'Nowa grupa' NoRoles: 'Nie znaleziono ról' + PERMISSIONS: Uprawnienia + PLURALNAME: Grupy + PLURALS: + one: Grupa + few: Grup + many: Grup + other: '{count} grup' Parent: 'Grupa nadrzędna' + ROLES: Role + ROLESDESCRIPTION: 'Role są wstępnie zdefiniowanymi zestawami uprawnień i można je przypisać do grup.
TW razie potrzeby są one dziedziczone z grup nadrzędnych.' RolesAddEditLink: 'Zarządzaj rolami' + SINGULARNAME: Grupa Sort: 'Kolejność Sortowania' has_many_Permissions: Zezwolenia many_many_Members: Użytkownicy SilverStripe\Security\LoginAttempt: + Email: 'Adres e-mail' + EmailHashed: 'Adres e-mail (hashed)' IP: 'Adres IP' + PLURALNAME: 'Próby logowania' + PLURALS: + one: 'Próba logowania' + few: 'Prób logowania' + many: 'Próby logowania {count}' + other: 'Próby logowania {count}' + SINGULARNAME: 'Próba logowania' Status: Status SilverStripe\Security\Member: ADDGROUP: 'Dodaj grupę' BUTTONCHANGEPASSWORD: 'Zmień hasło' BUTTONLOGIN: Zaloguj BUTTONLOGINOTHER: 'Zaloguj jako ktoś inny' + BUTTONLOGOUT: 'Wyloguj się' BUTTONLOSTPASSWORD: 'Zgubiłem hasło' CONFIRMNEWPASSWORD: 'Potwierdź nowe hasło' CONFIRMPASSWORD: 'Potwierdź hasło' + CURRENT_PASSWORD: 'Aktualne hasło' + EDIT_PASSWORD: 'Nowe hasło' EMAIL: E-mail EMPTYNEWPASSWORD: 'Nowe hasło nie może być puste, spróbuj ponownie.' ENTEREMAIL: 'Wpisz adres e-mail aby otrzymać link do zmiany hasła.' @@ -113,12 +243,23 @@ pl: ERRORWRONGCRED: 'Podane dane są niepoprawne. Proszę spróbować ponownie.' FIRSTNAME: Imię INTERFACELANG: 'Język interfejsu' + KEEPMESIGNEDIN: 'Zapamiętaj mnie' LOGGEDINAS: 'Zostałeś zalogowany jako {name}.' NEWPASSWORD: 'Nowe hasło' PASSWORD: Hasło + PASSWORDEXPIRED: 'Twoje hasło wygasło. Prosimy ustawić nowe.' + PLURALNAME: Użytkownicy + PLURALS: + one: Użytkownik + few: '{count} użytkowników' + many: '{count} użytkowników' + other: '{count} użytkowników' + REMEMBERME: 'Pamiętaj mnie następnym razem? (przez {count} dni na tym urządzeniu)' + SINGULARNAME: Użytkownik SUBJECTPASSWORDCHANGED: 'Twoje hasło zostało zmienione' SUBJECTPASSWORDRESET: 'Twój link do zmiany hasła' SURNAME: Nazwisko + VALIDATIONADMINLOSTACCESS: 'Nie można usunąć wszystkich grup administracyjnych z Twojego profilu' ValidationIdentifierFailed: 'Nie można nadpisać istniejącego użytkownika #{id} o identycznym identyfikatorze ({name} = {value})' WELCOMEBACK: 'Witaj ponownie, {firstname}' YOUROLDPASSWORD: 'Twoje stare hasło' @@ -127,15 +268,42 @@ pl: db_LockedOutUntil: 'Zablokowany do' db_Password: Hasło db_PasswordExpiry: 'Data wygaśnięcia hasła' + SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: + AUTHENTICATORNAME: 'Formularz logowania użytkownika CMS' + BUTTONFORGOTPASSWORD: 'Zapomniałeś hasła?' + BUTTONLOGIN: 'Zaloguj mnie spowrotem' + BUTTONLOGOUT: 'Wyloguj się' + SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: + ERRORWRONGCRED: 'Podane dane są niepoprawne. Proszę spróbować ponownie.' + NoPassword: 'Hasło nie zostało skonfigurowane dla tego użytkownika.' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'E-mail i hasło' + SilverStripe\Security\MemberPassword: + PLURALNAME: 'Hasła użytkownika' + PLURALS: + one: 'Hasło użytkownika' + few: 'Haseł użytkownika' + many: 'Haseł użytkownika' + other: '{count} haseł użytkownika ' + SINGULARNAME: 'Hasło użytkownika' SilverStripe\Security\PasswordValidator: LOWCHARSTRENGTH: 'Proszę zwiększyć siłę hasła, dodając niektóre z następujących znaków: % s' PREVPASSWORD: 'Użyłeś już tego hasła wcześniej, proszę wybrać nowe' TOOSHORT: 'Hasło jest za krótkie, proszę podać {minimum} znaków lub więcej' SilverStripe\Security\Permission: AdminGroup: Administrator + CMS_ACCESS_CATEGORY: 'Dostęp do CMS''a' CONTENT_CATEGORY: 'Uprawnienie edycji treści' FULLADMINRIGHTS: 'Pełne prawa administracyjne' FULLADMINRIGHTS_HELP: 'Zatwierdza i nadpisuje wszystkie istniejące uprawnienia' + PERMISSIONS_CATEGORY: 'Uprawnienia ról i dostępu' + PLURALNAME: Uprawnienia + PLURALS: + one: Uprawnienie + few: Uprawnień + many: Uprawnień + other: '{count} uprawnień' + SINGULARNAME: Uprawnienie UserPermissionsIntro: 'Przydzielenie grup temu użytkownikowi spowoduje zmianę jego uprawnień. Odwołaj się do sekcji Grupy aby dowiedzieć się więcej o uprawnieniach grupowych.' SilverStripe\Security\PermissionCheckboxSetField: AssignedTo: 'przypisany do "{title}"' @@ -144,20 +312,41 @@ pl: FromRoleOnGroup: 'odziedziczone z roli "{roletitle}" w grupie "{grouptitle}"' SilverStripe\Security\PermissionRole: OnlyAdminCanApply: 'Tylko administrator może to zastosować' + PLURALNAME: Role + PLURALS: + one: Rola + few: ról + many: ról + other: '{count} ról' + SINGULARNAME: Rola Title: Tytuł SilverStripe\Security\PermissionRoleCode: + PLURALNAME: 'Kod roli uprawnienia' + PLURALS: + one: 'Kod roli uprawnienia' + few: 'Kodów ról uprawnień' + many: 'Kodów ról uprawnień' + other: '{count} kodów ról uprawnień' PermsError: 'Nie można przyporządkować uprzywilejowanego uprawnienia "{code}" (wymagane uprawnienie ADMIN)' + SINGULARNAME: 'Kod roli uprawnienia' + SilverStripe\Security\RememberLoginHash: + PLURALNAME: 'Hasła logowania' + PLURALS: + one: 'Hasło logowania' + few: 'Haseł logowania' + many: 'Haseł logowania' + other: '{count} haseł logowania' + SINGULARNAME: 'Hasło logowania' SilverStripe\Security\Security: ALREADYLOGGEDIN: 'Nie masz dostępu do tej strony. Jeśli posiadasz inne konto, które umożliwi Ci dostęp do tej strony, możesz się zalogować poniżej' BUTTONSEND: 'Wyślij mi link do zresetowania hasła' CHANGEPASSWORDBELOW: 'Możesz zmienić swoje hasło poniżej' CHANGEPASSWORDHEADER: 'Zmień swoje hasło' + CONFIRMLOGOUT: 'Kliknij przycisk poniżej, aby potwierdzić, że chcesz się wylogować.' ENTERNEWPASSWORD: 'Proszę wprowadż nowe hasło' ERRORPASSWORDPERMISSION: 'Musisz być zalogowany aby zmienić hasło' LOGIN: Logowanie + LOGOUT: 'Wyloguj się' LOSTPASSWORDHEADER: 'Nie pamiętam hasła' NOTEPAGESECURED: 'Ta strona jest zabezpieczona. Wpisz swoje dane a my wyślemy Ci potwierdzenie niebawem' - NOTERESETLINKINVALID: '

Link resetujący hasło wygasł lub jest nieprawidłowy.

Możesz poprosić o nowy tutaj lub zmień swoje hasło po zalogowaniu się.

' NOTERESETPASSWORD: 'Wpisz adres e-mail, na który mamy wysłać link gdzie możesz zresetować swoje hasło' - PASSWORDSENTHEADER: 'Link resetujący hasła został wysłany do ''{email}''' - PASSWORDSENTTEXT: 'Dziękujemy! Link resetujący hasło został wysłany do ''{email}'', o ile konto użytkownika dla takiego e-maila istnieje.' diff --git a/lang/pt.yml b/lang/pt.yml index b4b030690..2a7c645d2 100644 --- a/lang/pt.yml +++ b/lang/pt.yml @@ -1,9 +1,6 @@ pt: SilverStripe\Forms\ConfirmedPasswordField: SHOWONCLICKTITLE: 'Mudar password' - SilverStripe\Forms\DateField: - NOTSET: 'Não inserido' - TODAY: Hoje SilverStripe\Forms\DropdownField: CHOOSE: (Escolha) SilverStripe\Forms\Form: diff --git a/lang/pt_BR.yml b/lang/pt_BR.yml index fc7c41713..10d37fa3d 100644 --- a/lang/pt_BR.yml +++ b/lang/pt_BR.yml @@ -3,9 +3,6 @@ pt_BR: SHOWONCLICKTITLE: 'Trocar senha' SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: R$ - SilverStripe\Forms\DateField: - NOTSET: 'não informado' - TODAY: hoje SilverStripe\Forms\DropdownField: CHOOSE: Selecione SilverStripe\Forms\Form: diff --git a/lang/ro.yml b/lang/ro.yml index aa855a0d0..e02135a75 100644 --- a/lang/ro.yml +++ b/lang/ro.yml @@ -4,8 +4,6 @@ ro: BETWEEN: 'Parola trebuie să conțină între {min} și {max} caractere.' MAXIMUM: 'Parola trebuie să conțină cel mult {max} caractere.' SHOWONCLICKTITLE: 'Schimbare Parola' - SilverStripe\Forms\DateField: - TODAY: astăzi SilverStripe\Forms\DropdownField: CHOOSE: (Alege) SilverStripe\Forms\GridField\GridField: diff --git a/lang/ru.yml b/lang/ru.yml index 5d8cf119d..add72be7f 100644 --- a/lang/ru.yml +++ b/lang/ru.yml @@ -33,8 +33,6 @@ ru: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'не установлено' - TODAY: сегодня VALIDDATEFORMAT2: 'Пожалуйста, задайте верный формат даты ({format})' VALIDDATEMAXDATE: 'Требуется значение даты, совпадающее с максимальным ({date}) или более старое' VALIDDATEMINDATE: 'Требуется значение даты, совпадающее с минимальным ({date}) или более новое' @@ -82,7 +80,6 @@ ru: RelationSearch: 'Поиск отношений' ResetFilter: Сброс SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Удалить Delete: Удалить DeletePermissionsFailure: 'Нет прав на удаление' EditPermissionsFailure: 'Не достаточно прав для удаления записи' @@ -94,8 +91,6 @@ ru: DeletePermissionsFailure: 'Нет прав на удаление' Deleted: 'Удалено {type} {name}' Save: Сохранить - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Редактировать SilverStripe\Forms\GridField\GridFieldPaginator: OF: из Page: Страница @@ -344,7 +339,4 @@ ru: LOGOUT: Выйти LOSTPASSWORDHEADER: 'Восстановление пароля' NOTEPAGESECURED: 'Эта страница защищена. Пожалуйста, введите свои учетные данные для входа.' - NOTERESETLINKINVALID: '

Неверная ссылка переустановки пароля или время действия ссылки истекло.

Вы можете повторно запросить ссылку, щелкнув здесь, или поменять пароль, войдя в систему.

' NOTERESETPASSWORD: 'Введите Ваш адрес email, и Вам будет отправлена ссылка, по которой Вы сможете переустановить свой пароль' - PASSWORDSENTHEADER: 'Ссылка для переустановки пароля выслана на ''{email}''' - PASSWORDSENTTEXT: 'Ссылка переустановки пароля была выслана на адрес ''{email}'' (письмо дойдет до получателя только в том случае, если аккаунт с таким электронным адресом действительно зарегистрирован).' diff --git a/lang/sk.yml b/lang/sk.yml index dba7ecaaf..88f4bf260 100644 --- a/lang/sk.yml +++ b/lang/sk.yml @@ -37,8 +37,6 @@ sk: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: nezadané - TODAY: dnes VALIDDATEFORMAT2: 'Prosím zadajte platný formát dátumu ({format})' VALIDDATEMAXDATE: 'Váš dátum musí byť starší alebo odpovedajúci maximu povoleného dátumu ({date})' VALIDDATEMINDATE: 'Váš dátum musí byť novší alebo odpovedajúci minimu povoleného dátumu ({date})' @@ -78,7 +76,6 @@ sk: RelationSearch: 'Vzťah hľadania' ResetFilter: Reset SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Zmazať Delete: Zmazať DeletePermissionsFailure: 'Žiadne oprávnenia zmazať' EditPermissionsFailure: 'Žiadne oprávnenie pre odpojenie záznamu' @@ -90,12 +87,8 @@ sk: DeletePermissionsFailure: 'Žiadne oprávnenia zmazať' Deleted: 'Zmazané {type} {name}' Save: Uložiť - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Editovať SilverStripe\Forms\GridField\GridFieldPaginator: Page: Stránka - SilverStripe\Forms\GridField\GridFieldVersionedState: - ONLIVEONLYSHORT: 'Len publikované' SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Množstvo FIELDLABELCURRENCY: Mena @@ -235,7 +228,4 @@ sk: LOGIN: Prihlásiť LOSTPASSWORDHEADER: 'Zabudnuté heslo' NOTEPAGESECURED: 'Táto stránka je zabezpečená. Zadajte svoje prihlasovacie údaje a my Vám zároveň pošleme práva.' - NOTERESETLINKINVALID: '

Odkaz na resetovanie hesla nie je platný alebo je vypršala jeho platnosť.

Môžete požiadať o nový tu alebo zmeňte svoje heslo po prihlásení.

' NOTERESETPASSWORD: 'Zadajte svoju e-mailovú adresu a my Vám pošleme odkaz na resetovanie hesla' - PASSWORDSENTHEADER: 'Odkaz na resetovanie hesla bol odoslaný na ''{email}''' - PASSWORDSENTTEXT: 'Ďakujeme! Resetovací odkaz bol odoslaný na ''''{email}'''', pokiaľ účet existuje pre túto emailovú adresu.' diff --git a/lang/sl.yml b/lang/sl.yml index 7e5138547..5496aff5f 100644 --- a/lang/sl.yml +++ b/lang/sl.yml @@ -5,8 +5,6 @@ sl: MAXIMUM: 'Geslo je lahko dolgo največ {max} znakov.' SHOWONCLICKTITLE: 'Spremeni geslo' SilverStripe\Forms\DateField: - NOTSET: 'ni nastavljeno' - TODAY: danes VALIDDATEFORMAT2: 'Prosim, vnesite ustrezno obliko datuma ({format})' VALIDDATEMAXDATE: 'Datum mora biti starejši ali enak največjemu dovoljenemu datumu ({date})' VALIDDATEMINDATE: 'Datum mora biti novejši ali enak najmanjšemu dovoljenemu datumu ({date})' @@ -40,7 +38,6 @@ sl: RelationSearch: 'Povezano iskanje' ResetFilter: Ponastavi SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Izbriši Delete: Izbriši DeletePermissionsFailure: 'Ni dovoljenja za brisanje' UnlinkRelation: 'Odstrani povezavo' @@ -51,8 +48,6 @@ sl: DeletePermissionsFailure: 'Ni dovoljenja za brisanje' Deleted: 'Izbrisanih {type} {name}' Save: Shrani - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Uredi SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Znesek FIELDLABELCURRENCY: Valuta @@ -140,7 +135,4 @@ sl: LOGIN: Prijava LOSTPASSWORDHEADER: 'Izgubljeno geslo' NOTEPAGESECURED: 'Stran je zaščitena. Da bi lahko nadaljevali, vpišite svoje podatke.' - NOTERESETLINKINVALID: '

Povezava za ponastavitev gesla je napačna ali pa je njena veljavnost potekla.

Tukaj lahko zaprosite za novo povezavo or pa zamenjate geslo, ko se prijavite v sistem.

' NOTERESETPASSWORD: 'Vpišite e-naslov, na katerega vam bomo poslali povezavo za ponastavitev gesla' - PASSWORDSENTHEADER: 'Povezava za ponastavitev gesla je bila poslana na e-naslov ''{email}''.' - PASSWORDSENTTEXT: 'Hvala! Povezava za ponastavitev gesla je bila poslana na e-naslov ''{email}'', ki je naveden kot e-naslov vašega računa. ' diff --git a/lang/sl_SI.yml b/lang/sl_SI.yml index 01fb8b0a3..ec4ad09e8 100644 --- a/lang/sl_SI.yml +++ b/lang/sl_SI.yml @@ -7,8 +7,6 @@ sl_SI: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: € SilverStripe\Forms\DateField: - NOTSET: 'ni nastavljeno' - TODAY: danes VALIDDATEFORMAT2: 'Prosimo vnesite veljavno obliko datuma ({format})' SilverStripe\Forms\DropdownField: CHOOSE: (Izberi) @@ -24,7 +22,6 @@ sl_SI: Print: Natisni ResetFilter: Resetiraj SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Izbriši Delete: Izbriši UnlinkRelation: 'Odstrani povezavo' SilverStripe\Forms\GridField\GridFieldDetailForm: @@ -34,8 +31,6 @@ sl_SI: DeletePermissionsFailure: 'Nimate pravic za brisanje' Deleted: 'Izbrisano {type} {name}' Save: Shrani - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Uredi SilverStripe\ORM\FieldType\DBBoolean: NOANSWER: Ne YESANSWER: Da diff --git a/lang/sr.yml b/lang/sr.yml index 4a989ee97..622b657b3 100644 --- a/lang/sr.yml +++ b/lang/sr.yml @@ -7,8 +7,6 @@ sr: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: дин. SilverStripe\Forms\DateField: - NOTSET: 'није подешено' - TODAY: данас VALIDDATEFORMAT2: 'Молимо Вас да унесете исправан формат датума ({format})' VALIDDATEMAXDATE: 'Датум не сме бити после ({date})' VALIDDATEMINDATE: 'Датум не сме бити пре ({date})' @@ -41,7 +39,6 @@ sr: RelationSearch: 'Претраживање релације' ResetFilter: 'Врати у пређашње стање' SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Избриши Delete: Избриши DeletePermissionsFailure: 'Немате дозволу за брисање' EditPermissionsFailure: 'Немате дозволу да раскинете линк са записом' @@ -53,8 +50,6 @@ sr: DeletePermissionsFailure: 'Немате право брисања' Deleted: 'Избрисано {type} {name}' Save: Сачувај - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Измени SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Износ FIELDLABELCURRENCY: Валута @@ -156,7 +151,4 @@ sr: ERRORPASSWORDPERMISSION: 'Морате да будете пријављени да бисте променили своју лозинку!' LOGIN: Пријављивање NOTEPAGESECURED: 'Ова страна је обезбеђена. Унесите своје податке и ми ћемо вам послати садржај.' - NOTERESETLINKINVALID: '

Линк за ресетовање лозинке је погрешан или је истекло време за његово коришћење.

Можете да захтевате нови овде или да промените Вашу лозинку након што се пријавите.

' NOTERESETPASSWORD: 'Унесите своју адресу е-поште и ми ћемо вам послати линк помоћу којег можете да промените своју лозинку' - PASSWORDSENTHEADER: 'Линк за ресетовање лозинке послат је на адресу е-поште: ''{email}''' - PASSWORDSENTTEXT: 'Хвала Вам! Линк за ресетовање лозинке је послат не адресу е-поште ''{email}''. Порука ће стићи примаоцу само ако постоји регистрован налог са том адресом е-поште.' diff --git a/lang/sr@latin.yml b/lang/sr@latin.yml index 957457b82..f91aa9337 100644 --- a/lang/sr@latin.yml +++ b/lang/sr@latin.yml @@ -7,8 +7,6 @@ sr@latin: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: din. SilverStripe\Forms\DateField: - NOTSET: 'nije podešeno' - TODAY: danas VALIDDATEFORMAT2: 'Molimo Vas da unesete ispravan format datuma ({format})' VALIDDATEMAXDATE: 'Datum ne sme biti posle ({date})' VALIDDATEMINDATE: 'Datum ne sme biti pre ({date})' @@ -41,7 +39,6 @@ sr@latin: RelationSearch: 'Pretraživanje relacije' ResetFilter: 'Vrati u pređašnje stanje' SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Izbriši Delete: Izbriši DeletePermissionsFailure: 'Nemate dozvolu za brisanje' EditPermissionsFailure: 'Nemate dozvolu da raskinete link sa zapisom' @@ -53,8 +50,6 @@ sr@latin: DeletePermissionsFailure: 'Nemate pravo brisanja' Deleted: 'Izbrisano {type} {name}' Save: Sačuvaj - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Izmeni SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Iznos FIELDLABELCURRENCY: Valuta @@ -155,7 +150,4 @@ sr@latin: ERRORPASSWORDPERMISSION: 'Morate da budete prijavljeni da biste promenili svoju lozinku!' LOGIN: Prijavljivanje NOTEPAGESECURED: 'Ova strana je obezbeđena. Unesite svoje podatke i mi ćemo vam poslati sadržaj.' - NOTERESETLINKINVALID: '

Link za resetovanje lozinke je pogrešan ili je isteklo vreme za njegovo korišćenje.

Možete da zahtevate novi ovde ili da promenite Vašu lozinku nakon što se prijavite.

' NOTERESETPASSWORD: 'Unesite svoju adresu e-pošte i mi ćemo vam poslati link pomoću kojeg možete da promenite svoju lozinku' - PASSWORDSENTHEADER: 'Link za resetovanje lozinke poslat je na adresu e-pošte: ''{email}''' - PASSWORDSENTTEXT: 'Hvala Vam! Link za resetovanje lozinke je poslat ne adresu e-pošte ''{email}''. Poruka će stići primaocu samo ako postoji registrovan nalog sa tom adresom e-pošte.' diff --git a/lang/sr_RS.yml b/lang/sr_RS.yml index 62d6aef15..298049430 100644 --- a/lang/sr_RS.yml +++ b/lang/sr_RS.yml @@ -7,8 +7,6 @@ sr_RS: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: дин. SilverStripe\Forms\DateField: - NOTSET: 'није подешено' - TODAY: данас VALIDDATEFORMAT2: 'Молимо Вас да унесете исправан формат датума ({format})' VALIDDATEMAXDATE: 'Датум не сме бити после ({date})' VALIDDATEMINDATE: 'Датум не сме бити пре ({date})' @@ -41,7 +39,6 @@ sr_RS: RelationSearch: 'Претраживање релације' ResetFilter: 'Врати у пређашње стање' SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Избриши Delete: Избриши DeletePermissionsFailure: 'Немате дозволу за брисање' EditPermissionsFailure: 'Немате дозволу да раскинете линк са записом' @@ -53,8 +50,6 @@ sr_RS: DeletePermissionsFailure: 'Немате право брисања' Deleted: 'Избрисано {type} {name}' Save: Сачувај - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Измени SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Износ FIELDLABELCURRENCY: Валута @@ -155,7 +150,4 @@ sr_RS: ERRORPASSWORDPERMISSION: 'Морате да будете пријављени да бисте променили своју лозинку!' LOGIN: Пријављивање NOTEPAGESECURED: 'Ова страна је обезбеђена. Унесите своје податке и ми ћемо вам послати садржај.' - NOTERESETLINKINVALID: '

Линк за ресетовање лозинке је погрешан или је истекло време за његово коришћење.

Можете да захтевате нови овде или да промените Вашу лозинку након што се пријавите.

' NOTERESETPASSWORD: 'Унесите своју адресу е-поште и ми ћемо вам послати линк помоћу којег можете да промените своју лозинку' - PASSWORDSENTHEADER: 'Линк за ресетовање лозинке послат је на адресу е-поште: ''{email}''' - PASSWORDSENTTEXT: 'Хвала Вам! Линк за ресетовање лозинке је послат не адресу е-поште ''{email}''. Порука ће стићи примаоцу само ако постоји регистрован налог са том адресом е-поште.' diff --git a/lang/sr_RS@latin.yml b/lang/sr_RS@latin.yml index c4c4b6900..453ffa17d 100644 --- a/lang/sr_RS@latin.yml +++ b/lang/sr_RS@latin.yml @@ -7,8 +7,6 @@ sr_RS@latin: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: din. SilverStripe\Forms\DateField: - NOTSET: 'nije podešeno' - TODAY: danas VALIDDATEFORMAT2: 'Molimo Vas da unesete ispravan format datuma ({format})' VALIDDATEMAXDATE: 'Datum ne sme biti posle ({date})' VALIDDATEMINDATE: 'Datum ne sme biti pre ({date})' @@ -41,7 +39,6 @@ sr_RS@latin: RelationSearch: 'Pretraživanje relacije' ResetFilter: 'Vrati u pređašnje stanje' SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Izbriši Delete: Izbriši DeletePermissionsFailure: 'Nemate dozvolu za brisanje' EditPermissionsFailure: 'Nemate dozvolu da raskinete link sa zapisom' @@ -53,8 +50,6 @@ sr_RS@latin: DeletePermissionsFailure: 'Nemate pravo brisanja' Deleted: 'Izbrisano {type} {name}' Save: Sačuvaj - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Izmeni SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Iznos FIELDLABELCURRENCY: Valuta @@ -156,7 +151,4 @@ sr_RS@latin: ERRORPASSWORDPERMISSION: 'Morate da budete prijavljeni da biste promenili svoju lozinku!' LOGIN: Prijavljivanje NOTEPAGESECURED: 'Ova strana je obezbeđena. Unesite svoje podatke i mi ćemo vam poslati sadržaj.' - NOTERESETLINKINVALID: '

Link za resetovanje lozinke je pogrešan ili je isteklo vreme za njegovo korišćenje.

Možete da zahtevate novi ovde ili da promenite Vašu lozinku nakon što se prijavite.

' NOTERESETPASSWORD: 'Unesite svoju adresu e-pošte i mi ćemo vam poslati link pomoću kojeg možete da promenite svoju lozinku' - PASSWORDSENTHEADER: 'Link za resetovanje lozinke poslat je na adresu e-pošte: ''{email}''' - PASSWORDSENTTEXT: 'Hvala Vam! Link za resetovanje lozinke je poslat ne adresu e-pošte ''{email}''. Poruka će stići primaocu samo ako postoji registrovan nalog sa tom adresom e-pošte.' diff --git a/lang/sv.yml b/lang/sv.yml index 7a8b5b903..88a3b3959 100644 --- a/lang/sv.yml +++ b/lang/sv.yml @@ -1,10 +1,35 @@ sv: + SilverStripe\Admin\LeftAndMain: + VersionUnknown: okänd + SilverStripe\AssetAdmin\Forms\UploadField: + Dimensions: Dimensioner + EDIT: Redigera + EDITINFO: 'Redigera filen' + REMOVE: 'Ta bort' + SilverStripe\Control\ChangePasswordEmail_ss: + CHANGEPASSWORDFOREMAIL: 'Lösenordet för kontot med e-postadressen {email} har ändrats. Om du inte ändrade ditt lösenord, vänligen ändra lösenordet via länken nedan.' + CHANGEPASSWORDTEXT1: 'Du har ändrat ditt lösenord för' + CHANGEPASSWORDTEXT3: 'Ändra lösenord' + HELLO: Hej + SilverStripe\Control\Email\ForgotPasswordEmail_ss: + HELLO: Hej + TEXT1: 'Här är din' + TEXT2: 'återställningslänk för lösenord' + TEXT3: för + SilverStripe\Control\RequestProcessor: + INVALID_REQUEST: 'Ogiltig förfrågan' + REQUEST_ABORTED: 'Förfrågan avbruten' + SilverStripe\Core\Manifest\VersionProvider: + VERSIONUNKNOWN: Okänd SilverStripe\Forms\CheckboxField: NOANSWER: Nej YESANSWER: Ja + SilverStripe\Forms\CheckboxSetField_ss: + NOOPTIONSAVAILABLE: 'Inga tillgängliga val' SilverStripe\Forms\ConfirmedPasswordField: ATLEAST: 'Lösenord måste vara minst {min} tecken långa.' BETWEEN: 'Lösenord måste vara {min} till {max} tecken långa.' + CURRENT_PASSWORD_ERROR: 'Lösenordet du angav är inte korrekt' CURRENT_PASSWORD_MISSING: 'Du måste ange ditt nuvarande lösenord' LOGGED_IN_ERROR: 'Du måste vara inloggad för att ändra ditt lösenord' MAXIMUM: 'Lösenord får som längst vara {max} tecken långa.' @@ -12,17 +37,23 @@ sv: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: $ SilverStripe\Forms\DateField: - NOTSET: 'inte angivet' - TODAY: 'i dag' VALIDDATEFORMAT2: 'Var god att ange datumet i ett giltigt format ({format})' VALIDDATEMAXDATE: 'Angivet datum måste vara tidigare eller samma som det senaste godkända datumet ({date})' VALIDDATEMINDATE: 'Angivet datum måste vara senare eller samma som det tidigaste godkända datumet ({date})' + SilverStripe\Forms\DatetimeField: + VALIDDATEMAXDATETIME: 'Angivet datum måste vara tidigare eller samma som det senast godkända datumet ({datetime})' + VALIDDATETIMEFORMAT: 'Vänligen ange datum och tid i ett giltigt format ({format})' + VALIDDATETIMEMINDATE: 'Angivet datum måste vara senare eller samma som det tidigast godkända datumet ({datetime})' SilverStripe\Forms\DropdownField: CHOOSE: (Välj) + CHOOSE_MODEL: '(Välj {name})' SOURCE_VALIDATION: 'Vänligen välj att värde i listan. {value} är inget giltigt val' SilverStripe\Forms\EmailField: VALIDATION: 'Var snäll och ange en epostadress' + SilverStripe\Forms\FileUploadReceiver: + FIELDNOTSET: 'Hittade ingen filinformation' SilverStripe\Forms\Form: + BAD_METHOD: 'Detta formulär måste skickas med metoden {method}' CSRF_EXPIRED_MESSAGE: 'Din session har upphört. Var god och skicka in formuläret på nytt.' CSRF_FAILED_MESSAGE: 'Ett tekniskt fel uppstod. Var god klicka på bakåt-knappen, ladda om sidan i webbläsaren och försök igen' VALIDATIONPASSWORDSDONTMATCH: 'Lösenorden stämmer inte överrens ' @@ -31,10 +62,12 @@ sv: VALIDATOR: Validator VALIDCURRENCY: 'Var vänlig ange en korrekt valuta' SilverStripe\Forms\FormField: + EXAMPLE: 't.ex. {format}' NONE: ingen SilverStripe\Forms\GridField\GridField: Add: 'Lägg till {name}' CSVEXPORT: 'Exportera till CSV' + CSVIMPORT: 'Importera från CSV' Filter: Filtrera FilterBy: 'Filtrera på' Find: Hitta @@ -49,7 +82,6 @@ sv: RelationSearch: Relationssökning ResetFilter: Rensa SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: Radera Delete: Radera DeletePermissionsFailure: 'Rättighet för att radera saknas' EditPermissionsFailure: 'Rättigheter för avlänkning saknas' @@ -61,29 +93,65 @@ sv: DeletePermissionsFailure: 'Rättighet för att radera saknas' Deleted: 'Raderade {type} {name}' Save: Spara - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: Redigera + SilverStripe\Forms\GridField\GridFieldGroupDeleteAction: + UnlinkSelfFailure: 'Du kan inte radera dig själv från den här gruppen, då du då kommer att förlora dina admin-rättigheter' + SilverStripe\Forms\GridField\GridFieldPaginator: + OF: av + Page: Sida + View: Visa SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: Belopp FIELDLABELCURRENCY: Valuta + INVALID_CURRENCY: 'Valutan {currency} finns inte med i listan med tillåtna valutor' + SilverStripe\Forms\MultiSelectField: + SOURCE_VALIDATION: 'Vänligen välj ett värde i listan. {value} är inget giltigt val' SilverStripe\Forms\NullableField: IsNullLabel: 'Är NULL' SilverStripe\Forms\NumericField: VALIDATION: '''{value}'' är inget nummer, bara siffror (utan mellanslag) kan accepteras för det här fältet' SilverStripe\Forms\TimeField: VALIDATEFORMAT: 'Var god att ange tid i ett giltigt format ({format})' + SilverStripe\ORM\DataObject: + PLURALNAME: Dataobjekt + PLURALS: + one: 'Ett dataobjekt' + other: '{count} Dataobjekt' + SINGULARNAME: Dataobjekt SilverStripe\ORM\FieldType\DBBoolean: ANY: 'Vilken som helst' NOANSWER: Nej YESANSWER: Ja SilverStripe\ORM\FieldType\DBDate: + DAYS_SHORT_PLURALS: + one: '{count} dag' + other: '{count} dagar' + HOURS_SHORT_PLURALS: + one: '{count} timme' + other: '{count} timmar' LessThanMinuteAgo: 'mindre än en minut' + MINUTES_SHORT_PLURALS: + one: '{count} min' + other: '{count} min' + MONTHS_SHORT_PLURALS: + one: '{count} månad' + other: '{count} månader' + SECONDS_SHORT_PLURALS: + one: '{count} sek' + other: '{count} sek' TIMEDIFFAGO: '{difference} sen' TIMEDIFFIN: 'om {difference}' + YEARS_SHORT_PLURALS: + one: '{count} år' + other: '{count} år' SilverStripe\ORM\FieldType\DBEnum: ANY: 'Vilken som helst' + SilverStripe\ORM\Hierarchy: + LIMITED_TITLE: 'För många barn ({count})' SilverStripe\ORM\Hierarchy\Hierarchy: InfiniteLoopNotAllowed: 'Oändlig loop hittades i hierarkin "{type}". Var vänlig ändra föräldern för att lösa detta' + LIMITED_TITLE: 'För många barn ({count})' + SilverStripe\ORM\ValidationException: + DEFAULT_ERROR: Valideringsfel SilverStripe\Security\BasicAuth: ENTERINFO: 'Var god ange användarnamn och lösenord' ERRORNOTADMIN: 'Den användaren är inte administratör' @@ -92,34 +160,58 @@ sv: PASSWORDEXPIRED: '

Ditt lösenard har gått ut. Vänligen ange ett nytt.

' SilverStripe\Security\CMSSecurity: INVALIDUSER: '

Ogiltig användare. Vänligen ange dina inloggnings-uppgifter igen för att fortsätta.

' + LOGIN_MESSAGE: '

Din session har upphört på grund av inaktivitet

' + LOGIN_TITLE: 'Fortsätt där du slutade genom att logga in igen' SUCCESS: Framgång SUCCESSCONTENT: '

Inloggningen lyckades. Klicka här om du inte skickas vidare automatiskt.

' + SUCCESS_TITLE: 'Inloggning lyckades' SilverStripe\Security\Group: AddRole: 'Lägg till roll för den här gruppen' Code: Gruppkod DefaultGroupTitleAdministrators: Administratörer DefaultGroupTitleContentAuthors: Författare Description: Beskrivning + GROUPNAME: Gruppnamn GroupReminder: 'Om du väljer en förälder till gruppen så kommer gruppen ärva alla förälderns roller' HierarchyPermsError: 'Den överordnade gruppen "{group}" kan inte ges priviligerad tillgång (adminrättigheter krävs)' Locked: 'Låst?' + MEMBERS: Medlemmar + NEWGROUP: 'Ny grupp' NoRoles: 'Inga roller fun' + PERMISSIONS: Behörigheter + PLURALNAME: Grupper + PLURALS: + one: 'En grupp' + other: '{count} grupper' Parent: 'Överordnad grupp' + ROLES: Roller + ROLESDESCRIPTION: 'Roller är fördefinierade samlingar med behörigheter och kan tilldelas grupper.
De ärvs från föräldragrupper om det krävs.' RolesAddEditLink: 'Hantera roller' + SINGULARNAME: Grupp Sort: Sorteringsordning has_many_Permissions: Behörigheter many_many_Members: Medlemmar SilverStripe\Security\LoginAttempt: + Email: E-postadress + EmailHashed: 'E-postadress (hash)' IP: IP-adress + PLURALNAME: Inloggningsförsök + PLURALS: + one: 'Ett inloggningsförsök' + other: '{count} inloggningsförsök' + SINGULARNAME: Inloggningsförsök Status: Status SilverStripe\Security\Member: ADDGROUP: 'Lägg till grupp' BUTTONCHANGEPASSWORD: 'Ändra lösenord' BUTTONLOGIN: 'Logga in' BUTTONLOGINOTHER: 'Logga in som annan användare' + BUTTONLOGOUT: 'Logga ut' BUTTONLOSTPASSWORD: 'Jag har glömt mitt lösenord' CONFIRMNEWPASSWORD: 'Bekräfta nytt lösenord' CONFIRMPASSWORD: 'Bekräfta lösenord' + CURRENT_PASSWORD: 'Nuvarande lösenord' + EDIT_PASSWORD: 'Nytt lösenord' EMAIL: E-post EMPTYNEWPASSWORD: 'Det nya lösenordet kan inte vara tomt, vänligen försök igen' ENTEREMAIL: 'Ange en e-postadress för att få en återställningslänk för lösenordet.' @@ -129,13 +221,21 @@ sv: ERRORWRONGCRED: 'Antingen e-postadressen eller lösenordet är fel. Försök igen.' FIRSTNAME: Förnamn INTERFACELANG: Gränssnittsspråk + KEEPMESIGNEDIN: 'Håll mig inloggad' LOGGEDINAS: 'Du är inloggad som {name}.' NEWPASSWORD: 'Nytt lösenord' PASSWORD: Lösenord PASSWORDEXPIRED: 'Ditt lösenord har gått ut. Vänligen ange ett nytt.' + PLURALNAME: Medlemmar + PLURALS: + one: 'En medlem' + other: '{count} medlemmar' + REMEMBERME: 'Kom ihåg mig nästa gång? (i {count} dagar på denna enhet)' + SINGULARNAME: Medlem SUBJECTPASSWORDCHANGED: 'Ditt lösenord har ändrats' SUBJECTPASSWORDRESET: 'Din återställningslänk' SURNAME: Efternamn + VALIDATIONADMINLOSTACCESS: 'Kan inte radera alla admin-grupper från din profil' ValidationIdentifierFailed: 'Kan inte skriva över medlem #{id} med samma identifierare ({name} = {value}))' WELCOMEBACK: 'Välkommen tillbaka, {firstname}' YOUROLDPASSWORD: 'Ditt gamla lösenord' @@ -144,15 +244,32 @@ sv: db_LockedOutUntil: 'Utelåst till' db_Password: Lösenord db_PasswordExpiry: 'Lösenordet upphör att gälla' + SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: + AUTHENTICATORNAME: 'CMS inloggnings-formulär' + BUTTONFORGOTPASSWORD: 'Glömt lösenord' + BUTTONLOGIN: 'Logga in igen' + BUTTONLOGOUT: 'Logga ut' + SilverStripe\Security\MemberAuthenticator\MemberAuthenticator: + ERRORWRONGCRED: 'De angivna uppgifterna verkar inte vara korrekta. Var god försök igen.' + NoPassword: 'Det finns inget lösenord för den här medlemmen' + SilverStripe\Security\MemberAuthenticator\MemberLoginForm: + AUTHENTICATORNAME: 'E-post & lösenord' SilverStripe\Security\PasswordValidator: LOWCHARSTRENGTH: 'Var god och stärk ditt lösenord genom att lägga till något av följande tecken: {chars}' PREVPASSWORD: 'Du har redan använt samma lösenord tidigare, var god och välj ett nytt lösenord' TOOSHORT: 'Lösenordet är för kort, det måste innehålla {minimum} eller fler tecken.' SilverStripe\Security\Permission: AdminGroup: Administratör + CMS_ACCESS_CATEGORY: CMS-åtkomst CONTENT_CATEGORY: Innehållsåtkomst FULLADMINRIGHTS: 'Fulla administrativa rättigheter' FULLADMINRIGHTS_HELP: 'Implicerar och gäller över alla andra tillskrivna rättigheter.' + PERMISSIONS_CATEGORY: 'Roller och åtkomstbehörigheter' + PLURALNAME: Behörigheter + PLURALS: + one: 'En behörighet' + other: '{count} behörigheter' + SINGULARNAME: Behörighet UserPermissionsIntro: 'Genom att välja grupper för denna användare så ändras användarens rättigheter. Gå till grupper för att se vilka rättigheter de olika grupperna har.' SilverStripe\Security\PermissionCheckboxSetField: AssignedTo: 'tilldelad till "{title}"' @@ -161,6 +278,11 @@ sv: FromRoleOnGroup: 'ärvt från roll "{roletitle}" i grupp "{grouptitle}"' SilverStripe\Security\PermissionRole: OnlyAdminCanApply: 'Endast administratörer kan tillämpa denna roll' + PLURALNAME: Roller + PLURALS: + one: 'En roll' + other: '{count} roller' + SINGULARNAME: Roll Title: Rollnamn SilverStripe\Security\PermissionRoleCode: PermsError: 'Koden "{code}" kan inte ges privilegierad tillgång (adminrättigheter krävs)' @@ -169,12 +291,11 @@ sv: BUTTONSEND: 'Skicka återställningslänk' CHANGEPASSWORDBELOW: 'Du kan ändra ditt lösenord nedan' CHANGEPASSWORDHEADER: 'Ändra ditt lösenord' + CONFIRMLOGOUT: 'Vänligen klicka på knappen nedan för att bekräfta att du vill logga ut.' ENTERNEWPASSWORD: 'Var god ange ett nytt lösenord.' ERRORPASSWORDPERMISSION: 'Du måste vara inloggad för att kunna ändra ditt lösenord!' LOGIN: 'Logga in' + LOGOUT: 'Logga ut' LOSTPASSWORDHEADER: 'Bortglömt lösenord' NOTEPAGESECURED: 'Den här sidan är låst. Fyll i dina uppgifter nedan så skickar vi dig vidare.' - NOTERESETLINKINVALID: '

Återställningslänk för lösenord är felaktig eller för gammal.

Du kan begära en ny här eller ändra ditt lösenord när du loggat in.

' NOTERESETPASSWORD: 'Ange din e-postadress så skickar vi en länk med vilken du kan återställa ditt lösenord' - PASSWORDSENTHEADER: 'Återställningslänk för lösenord har skickats till ''{email}''' - PASSWORDSENTTEXT: 'Tack en återställningslänk har skickats till ''{email}'', förutsatt att ett konto med den addressen finns.' diff --git a/lang/th.yml b/lang/th.yml index b30883ed4..a94e91ed4 100644 --- a/lang/th.yml +++ b/lang/th.yml @@ -2,9 +2,6 @@ th: SilverStripe\Forms\ConfirmedPasswordField: BETWEEN: 'รหัสผ่านต้องมีความยาวตัวอักษรอย่างน้อย {min} ถึง {max} ตัวอักษร' SHOWONCLICKTITLE: เปลี่ยนรหัสผ่าน - SilverStripe\Forms\DateField: - NOTSET: ไม่ต้องตั้งค่า - TODAY: วันนี้ SilverStripe\Forms\DropdownField: CHOOSE: (เลือก) SilverStripe\Forms\EmailField: @@ -30,7 +27,6 @@ th: Print: พิมพ์ ResetFilter: รีเซ็ต SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: ลบ Delete: ลบ DeletePermissionsFailure: ไม่ได้รับสิทธิ์ให้ลบได้ UnlinkRelation: ยกเลิกการลิงก์ diff --git a/lang/tr.yml b/lang/tr.yml index d354d3444..e40237592 100644 --- a/lang/tr.yml +++ b/lang/tr.yml @@ -6,9 +6,6 @@ tr: SHOWONCLICKTITLE: 'Parola Değiştir' SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: USD - SilverStripe\Forms\DateField: - NOTSET: ayarlanmamış - TODAY: bugün SilverStripe\Forms\DropdownField: CHOOSE: (Seçiniz) SilverStripe\Forms\Form: diff --git a/lang/uk.yml b/lang/uk.yml index ca0be2b5a..9c30b7d1f 100644 --- a/lang/uk.yml +++ b/lang/uk.yml @@ -4,9 +4,6 @@ uk: BETWEEN: 'Пароль повинен містити від {min} до {max} символів.' MAXIMUM: 'Пароль повинен містити не більше ніж {max} символів.' SHOWONCLICKTITLE: 'Змінити пароль' - SilverStripe\Forms\DateField: - NOTSET: 'не встановлено' - TODAY: сьогодні SilverStripe\Forms\DropdownField: CHOOSE: (Оберіть) SilverStripe\Forms\Form: diff --git a/lang/zh.yml b/lang/zh.yml index 792565ac6..748ee671c 100644 --- a/lang/zh.yml +++ b/lang/zh.yml @@ -10,8 +10,6 @@ zh: SilverStripe\Forms\CurrencyField: CURRENCYSYMBOL: 货币字符 SilverStripe\Forms\DateField: - NOTSET: 未设置 - TODAY: 今天 VALIDDATEFORMAT2: '请输入一个有效的日期格式 ({format})' VALIDDATEMAXDATE: '您的日期必须更早或者符合最大允许日期 ({date})' VALIDDATEMINDATE: '您的日期必须更迟或者符合最小允许日期 ({date})' @@ -46,7 +44,6 @@ zh: RelationSearch: 关系搜索 ResetFilter: 重设 SilverStripe\Forms\GridField\GridFieldDeleteAction: - DELETE_DESCRIPTION: 删除 Delete: 删除 DeletePermissionsFailure: 没有删除权限 EditPermissionsFailure: 没有解除记录链接的权限 @@ -58,8 +55,6 @@ zh: DeletePermissionsFailure: 没有删除权限 Deleted: '已删除的 {type} {name}' Save: 保存 - SilverStripe\Forms\GridField\GridFieldEditButton_ss: - EDIT: 编辑 SilverStripe\Forms\MoneyField: FIELDLABELAMOUNT: 金额 FIELDLABELCURRENCY: 货币 @@ -171,7 +166,4 @@ zh: LOGIN: 登录 LOSTPASSWORDHEADER: 忘记密码 NOTEPAGESECURED: 该页面受安全保护。请在下面输入您的证书,然后我们会立即将您引导至该页面。 - NOTERESETLINKINVALID: '

密码重设链接无效或已过期。

您可以在这里 要求一个新的或在登录后更改您的密码。

' NOTERESETPASSWORD: 请输入您的电子邮件地址,然后我们会将一个链接发送给您,您可以用它来重设您的密码 - PASSWORDSENTHEADER: '密码重设链接已发送至''{email}''' - PASSWORDSENTTEXT: '谢谢!复位链接已发送到 ''{email}'',假定此电子邮件地址存在一个帐户。' From a843e136e8f653d2a979cdcdf0ced38575ae0e49 Mon Sep 17 00:00:00 2001 From: Aaron Carlino Date: Fri, 9 Nov 2018 11:09:07 +1300 Subject: [PATCH 17/17] Added 4.0.5 changelog --- docs/en/04_Changelogs/4.0.5.md | 100 +++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/docs/en/04_Changelogs/4.0.5.md b/docs/en/04_Changelogs/4.0.5.md index 0fc65d7f7..52bb06871 100644 --- a/docs/en/04_Changelogs/4.0.5.md +++ b/docs/en/04_Changelogs/4.0.5.md @@ -10,3 +10,103 @@ behaviour to that of SilverStripe 3 where `Extension` instances are of lowest im default value. If you rely on your `Extension` or module providing an overriding config value, please move this to yaml. + +## Change Log + +### Security + + * 2018-11-02 [aebaa46](https://github.com/silverstripe/silverstripe-admin/commit/aebaa46f1f8834fefa09bdaf85bfdd51229f58b3) Add CSRF to Apollo (Aaron Carlino) - See [ss-2018-007](https://www.silverstripe.org/download/security-releases/ss-2018-007) + * 2018-08-21 [8d7c2dafa](https://github.com/silverstripe/silverstripe-framework/commit/8d7c2dafabad505d769f3774c44e0595fb1a4cd9) Add confirmation token to dev/build (Loz Calver) - See [ss-2018-019](https://www.silverstripe.org/download/security-releases/ss-2018-019) + * 2018-07-29 [9aabe0a0f](https://github.com/silverstripe/silverstripe-framework/commit/9aabe0a0f7a061d87cc92923f8811e14d7a032f5) Ignore arguments in mysqli::real_connect backtrace calls (Robbie Averill) - See [ss-2018-018](https://www.silverstripe.org/download/security-releases/ss-2018-018) + * 2018-05-08 [19fdebfa2](https://github.com/silverstripe/silverstripe-framework/commit/19fdebfa245506626561bc9626d9ac325acb14da) Remove dotm, potm, jar, css, js, xltm from default File.allowed_extensions (Robbie Averill) - See [ss-2018-014](https://www.silverstripe.org/download/security-releases/ss-2018-014) + * 2018-04-11 [577138882](https://github.com/silverstripe/silverstripe-framework/commit/577138882163e4b8782ea043487944d30d88e753) Restrict non-admins from being assigned to admin groups (Damian Mooyman) - See [ss-2018-001](https://www.silverstripe.org/download/security-releases/ss-2018-001) + +### API Changes + + * 2017-09-12 [c54b07a95](https://github.com/silverstripe/silverstripe-framework/commit/c54b07a9528aeef3907b4342a725af10d9797cd8) Update to use new chromedriver + behat-extension + facebook/webdriver (Damian Mooyman) + +### Features and Enhancements + + * 2018-04-19 [1509a12fd](https://github.com/silverstripe/silverstripe-framework/commit/1509a12fdf0fe8cbd300271fd5c60c3d76647d84) Only run coverage test as a cron (Damian Mooyman) + * 2018-04-09 [87d69ba7](https://github.com/silverstripe/silverstripe-cms/commit/87d69ba75366ff63563e5b9b159fb643daa4f1d7) Use i18n template for page tree title (Damian Mooyman) + * 2018-03-05 [32637413d](https://github.com/silverstripe/silverstripe-framework/commit/32637413deceb1a3c647fd51a78e1352e91ee15a) Improve upgrade rules to support advanced upgrader rewrites (#7903) (Damian Mooyman) + * 2018-03-05 [8c35e339](https://github.com/silverstripe/silverstripe-cms/commit/8c35e3391cf334917c5e314c6f1c459e9d06fbbc) Improve upgrade rules to support advanced upgrader rewrites (#2114) (Damian Mooyman) + * 2018-03-01 [61cfcc5](https://github.com/silverstripe/silverstripe-versioned/commit/61cfcc52a46895b6ff7fdb12956e01c48bfcf343) Improve upgrade rules to support advanced upgrader rewrites (Damian Mooyman) + * 2018-03-01 [e77e0f7](https://github.com/silverstripe/silverstripe-assets/commit/e77e0f758ed243a249c6056dbfc44f48b9fa535d) Improve upgrade rules to support advanced upgrader rewrites (Damian Mooyman) + * 2018-02-12 [9ce21338a](https://github.com/silverstripe/silverstripe-framework/commit/9ce21338a3083c80128c5923eab3d8b968f4dd83) composer.json missing notice (zanderwar) + * 2017-11-15 [c7ab5846d](https://github.com/silverstripe/silverstripe-framework/commit/c7ab5846df7e3f460b1c38e04a0946a914a35c19) Don't infer trace if explicitly provided (Damian Mooyman) + +### Bugfixes + + * 2018-09-18 [bbe7c66](https://github.com/silverstripe/silverstripe-asset-admin/commit/bbe7c660cf40d4c942eaf6e76755eeaf46c63471) Add `AssetAdmin::getMinimalistObjectFromData()` to build file metadata for UploadField (#829) (Maxime Rainville) + * 2018-09-03 [1c4311d](https://github.com/silverstripe/silverstripe-asset-admin/commit/1c4311d4e6548600272daa0ce83afa12cf7e99c3) fix description for docs.silverstripe.org (wernerkrauss) + * 2018-09-03 [b922c0d73](https://github.com/silverstripe/silverstripe-framework/commit/b922c0d7327b5d0222dd280afcb64f83a09ea859) Check scheme is truthy before setting it to the request (Robbie Averill) + * 2018-08-28 [d651d0fbf](https://github.com/silverstripe/silverstripe-framework/commit/d651d0fbfcababeaf317b27cb00b4f33b9d99eab) Use base class (not remapping target class) when looking up whether object is versioned (Robbie Averill) + * 2018-07-26 [fea9ef7](https://github.com/silverstripe/silverstripe-admin/commit/fea9ef7d2a53904086f9fad6eedba7bb307c8578) #579 BUG Ambiguous column RecordID when doing batch actions (Ed Linklater) + * 2018-06-13 [a2a8004](https://github.com/silverstripe/silverstripe-admin/commit/a2a800464b8f430529ee291a8b75e422ceca7914) Update user help link to 4 (Sacha Judd) + * 2018-06-13 [932eb2b2](https://github.com/silverstripe/silverstripe-cms/commit/932eb2b22dfe6c30473b1cf973661c28c5b9c635) Fix CMS components failing to register on other CMS sections (#2182) (Damian Mooyman) + * 2018-06-12 [7b04949ca](https://github.com/silverstripe/silverstripe-framework/commit/7b04949caa11d6e5c8cace3453cf2ed29996fb06) Remove duplicate key (Damian Mooyman) + * 2018-06-12 [c9bcc07](https://github.com/silverstripe/silverstripe-assets/commit/c9bcc070fdbb76fef49f7564eb98a4a81e2ed65f) Remove duplicate .upgrade.yml keys (Damian Mooyman) + * 2018-06-12 [674b92c](https://github.com/silverstripe/silverstripe-admin/commit/674b92c125488cb6bc43cade4c93e9adccb27e9b) Fix invalid .upgrade.yml (Damian Mooyman) + * 2018-06-11 [2a51f34c3](https://github.com/silverstripe/silverstripe-framework/commit/2a51f34c3e3c44acd603def241ac4447e715b165) Prevent canonical URL causing a redirect on CLI unless explicitly enabled (Damian Mooyman) + * 2018-06-07 [29f9b1c18](https://github.com/silverstripe/silverstripe-framework/commit/29f9b1c18fb38dab912a0b9dcae63eacae19335d) Fix linting issues (Damian Mooyman) + * 2018-06-07 [e37e3e174](https://github.com/silverstripe/silverstripe-framework/commit/e37e3e1746e56c866ee875f41a7fddf61c926d9f) Fix test that relies on implicit ID order breaking postgres (Damian Mooyman) + * 2018-06-07 [66f57bd4d](https://github.com/silverstripe/silverstripe-framework/commit/66f57bd4dac0bd4c8106f8071ddc45103c2643f2) Only set MYSQL_ATTR_INIT_COMMAND when using mysql driver (fixes #8103) (Loz Calver) + * 2018-06-06 [c070e989c](https://github.com/silverstripe/silverstripe-framework/commit/c070e989c4de41441d1061d2678b461f3f13d63b) Safely handle empty injector factory responses (Damian Mooyman) + * 2018-06-04 [41e601a03](https://github.com/silverstripe/silverstripe-framework/commit/41e601a036307065d9ea2ba8862f67be738d402f) Regression from #8009 (Daniel Hensby) + * 2018-06-01 [5a5ba1e5c](https://github.com/silverstripe/silverstripe-framework/commit/5a5ba1e5c001de161fbeb19d6d662391dccc4c1e) Fix: negative values in read only currency field (Jonathon Menz) + * 2018-06-01 [582c69d32](https://github.com/silverstripe/silverstripe-framework/commit/582c69d32fd8f18e6c06bc0b4c0a7e3e87e67966) Fix issue with Disabled DateField always display (not set). (Maxime Rainville) + * 2018-05-29 [1cbf27e0f](https://github.com/silverstripe/silverstripe-framework/commit/1cbf27e0f47c3547914b03193d0f5f77c87ff8d5) PHP 5.3 compat for referencing $this in closure, and make method public for same reason (Robbie Averill) + * 2018-05-21 [bf5b578](https://github.com/silverstripe/silverstripe-admin/commit/bf5b5787685765c35c175c303f3f7ee719ac9453) Adding a min-width to flexbox-area-grow that allows flex blocks to shrink below their content width (Guy) + * 2018-05-18 [953153500](https://github.com/silverstripe/silverstripe-framework/commit/953153500d490f5b5abf7283c34242c3b22a855a) Polymorphic relationship class columns have obsolete class names remapped (Robbie Averill) + * 2018-05-08 [97a8f56](https://github.com/silverstripe/silverstripe-admin/commit/97a8f56c43ddb3c77a5bbc452755d44afb9a9472) Add missing focus styles for preview options (fixes silverstripe/silverstripe-framework #2101) (Loz Calver) + * 2018-05-02 [80bf0fc48](https://github.com/silverstripe/silverstripe-framework/commit/80bf0fc48774b2a25f95feb24ffcc9df8e5ad77c) bad syntax (Daniel Hensby) + * 2018-04-18 [fe4b90edc](https://github.com/silverstripe/silverstripe-framework/commit/fe4b90edc0ead9c6c77d606101bfbf568a963fb4) Duplicating many_many relationships looses the extra fields in 4.0 (UndefinedOffset) + * 2018-04-17 [f83691e7f](https://github.com/silverstripe/silverstripe-framework/commit/f83691e7f7e7a75657df1211673b72d9cf4c4b4f) Make invalid dev actions 404 not 500 error (Damian Mooyman) + * 2018-04-17 [af3a9f3ec](https://github.com/silverstripe/silverstripe-framework/commit/af3a9f3ec8a5465f841c5aa8ee1faf40c1b76bf4) Duplicating many_many relationships looses the extra fields (fixes #7973) (UndefinedOffset) + * 2018-04-10 [e11ba9a2d](https://github.com/silverstripe/silverstripe-framework/commit/e11ba9a2d7c89a1ecea8613589f05399b45a33bf) Fix many_many through crashing ModelAdmin (Damian Mooyman) + * 2018-04-08 [eeac1d1](https://github.com/silverstripe/silverstripe-admin/commit/eeac1d11800e70f19055bfa2ba4aec8b6a9b2ccb) Fix issue with selected values in large trees breaking initialisation (#476) (Damian Mooyman) + * 2018-03-29 [4acec3356](https://github.com/silverstripe/silverstripe-framework/commit/4acec33562e4e1230092eee7d76c2b8061ffc914) Fixed bug in config merging priorities so that config values set by extensions are now least important instead of most important (Daniel Hensby) + * 2018-03-28 [dd44deacb](https://github.com/silverstripe/silverstripe-framework/commit/dd44deacb462d80dbbda507fdb4e9527f049d3bd) Fix for "too few parameters" error when using DBMultiEnum (Andreas Lindahl) + * 2018-03-22 [cf5a0984](https://github.com/silverstripe/silverstripe-cms/commit/cf5a0984addf308d2cb10df9b67386be2a080f18) Correct SilverStripeNavigator correctly in templates (Daniel Hensby) + * 2018-03-15 [d17d93f7](https://github.com/silverstripe/silverstripe-cms/commit/d17d93f784a6e01f3d396c55adc623d69a90261a) Remove SearchForm results() function from allowed_actions (Steve Dixon) + * 2018-03-11 [2b9faf46](https://github.com/silverstripe/silverstripe-cms/commit/2b9faf46fe6606a9236f9e1ec987f9a22689a2c7) Fix InSection failing on non-page controllers (Damian Mooyman) + * 2018-03-07 [bf2cee398](https://github.com/silverstripe/silverstripe-framework/commit/bf2cee3989028aaa461e9f0f929724b7738c1399) Bugfix - Correct duplicate nesting of 'Content' to be returned to template (Joe Harvey) + * 2018-03-06 [5fee4a81a](https://github.com/silverstripe/silverstripe-framework/commit/5fee4a81aa880338fba7bb72731fd2b7be4643de) Files dataobjects with missing asset shouldn't un-attach themselves from parent object on save (Damian Mooyman) + * 2018-03-05 [dde13493](https://github.com/silverstripe/silverstripe-cms/commit/dde134936825e196ca97cb86ac3f5bc24d52278e) Fix invalid css classname in virtualpage (Damian Mooyman) + * 2018-03-05 [985a0af](https://github.com/silverstripe/silverstripe-admin/commit/985a0af292bb833ba48fa907a1b75892182ec390) Fix page icons (Damian Mooyman) + * 2018-03-02 [3bd714d](https://github.com/silverstripe/silverstripe-assets/commit/3bd714d293c3f6c12e8f7a0b3c7e054d99b410bd) Typo in "audio file" translation (Robbie Averill) + * 2018-03-01 [40c2e299a](https://github.com/silverstripe/silverstripe-framework/commit/40c2e299a0a9a63b4e64e14dff95e9f7d480db6e) Fix "mb_stripos(): Empty delimiter" warning when no search-keywords are given for `DBText::ContextSummary`. (Roman Schmid) + * 2018-02-27 [d91c6ed](https://github.com/silverstripe/silverstripe-admin/commit/d91c6ed0dc699f769802e5d1310f3fe111dd8ecf) Fix $CMSVersion appearing visually (Damian Mooyman) + * 2018-02-26 [b27102f81](https://github.com/silverstripe/silverstripe-framework/commit/b27102f810e873d287fa04678a4ff242c40699f6) Fix incorrect assets created when ASSETS_PATH !== BASE_PATH . '/assets' (Damian Mooyman) + * 2018-02-22 [012bfec5](https://github.com/silverstripe/silverstripe-cms/commit/012bfec5bf8e0902f3325c8e7fb237d48bd189ad) Bug field help text translations no longer need to be HTML encoded (Rick Hambrook) + * 2018-02-20 [83c4ab8d](https://github.com/silverstripe/silverstripe-cms/commit/83c4ab8d180954b3d80d16ed5f5764e3c647ca6d) Fix test regressions in CMS page filters (Damian Mooyman) + * 2018-02-19 [cfe82e9](https://github.com/silverstripe/silverstripe-assets/commit/cfe82e912616ca230b8fd29fba3bd3270fac2502) Fix behaviour towards versioned but unstagable records (Damian Mooyman) + * 2018-02-19 [4fc8166](https://github.com/silverstripe/silverstripe-versioned/commit/4fc816653e84c0a883a01afe30e16e8bd4129f53) Fix behaviour towards versioned but unstagable records (Damian Mooyman) + * 2018-02-19 [0e26c0664](https://github.com/silverstripe/silverstripe-framework/commit/0e26c066440d2591401e84d9688cbeef0595afcc) Fix behaviour towards versioned but unstagable records (Damian Mooyman) + * 2018-02-19 [3be0478e](https://github.com/silverstripe/silverstripe-cms/commit/3be0478e1c40cd2b9f577818596c4222b365b6b6) Fix behaviour towards versioned but unstagable records (Damian Mooyman) + * 2018-02-19 [8be3930](https://github.com/silverstripe/silverstripe-versioned/commit/8be393061e8578c3bd9056c6540e5f0bbff43801) Fix doRollbackTo() writing old / unsaved version over restored version (Damian Mooyman) + * 2018-02-16 [86addea1d](https://github.com/silverstripe/silverstripe-framework/commit/86addea1d2a7b2e28ae8115279ae358bcb46648a) Split HTML manipulation to onadd, so elements are not accidentally duplicated (Christopher Joe) + * 2018-02-13 [c767e472d](https://github.com/silverstripe/silverstripe-framework/commit/c767e472dc494408460ef47c27b8d34475da4ac6) DataObject singleton creation (Jonathon Menz) + * 2018-02-13 [f2b82b1f7](https://github.com/silverstripe/silverstripe-framework/commit/f2b82b1f77a60de4bf1b5807e1b820aad263ae1b) Fix docs for configuring before/after a specific config file (Christopher Joe) + * 2018-02-13 [c6095cf](https://github.com/silverstripe/silverstripe-config/commit/c6095cfc0a07a74bb932e2191215d06f102e992a) Fix word boundary issue with pathname matching (Christopher Joe) + * 2018-02-13 [1d27a14](https://github.com/silverstripe/silverstripe-admin/commit/1d27a14be75efb33a503f7f1c15b093ab3b59c7f) Remove border-radius add hover states to non-active tabs (Sacha Judd) + * 2018-02-12 [ad52ced](https://github.com/silverstripe/silverstripe-versioned/commit/ad52ced4353b8abe312aeacfb2c95657169feedc) Prevent nested permissions from breaking recursive publishing (Damian Mooyman) + * 2018-02-12 [0f08f85](https://github.com/silverstripe/silverstripe-admin/commit/0f08f85508d01a578015848caff032ae0fd62e4c) improve the browser warning logic show (Christopher Joe) + * 2018-02-08 [d86e5dfc](https://github.com/silverstripe/silverstripe-cms/commit/d86e5dfc883267ffaa0c43e9ece7576c4f42ed61) remove now superfluous print action destroyer (Dylan Wagstaff) + * 2018-02-08 [d3278d547](https://github.com/silverstripe/silverstripe-framework/commit/d3278d5470165bba14ee5026453ec7d529901f42) Add Nested DB transaction support (#7848) (Daniel Hensby) + * 2018-02-08 [0a486b8f5](https://github.com/silverstripe/silverstripe-framework/commit/0a486b8f5705242de523489190f3975d55b3b3e6) Fix issue with CLIDebugView failing on class name of existing class (Damian Mooyman) + * 2018-02-06 [0094c19](https://github.com/silverstripe/silverstripe-admin/commit/0094c19304eea5ac02daf42095da341315dae84f) Add text-colour to status-archived, remove span.badge styles (Sacha Judd) + * 2018-02-06 [6b38031a1](https://github.com/silverstripe/silverstripe-framework/commit/6b38031a1e16e94d5bafcbcce4bdcb2d6b3680ed) Fix Director::test() not persisting removed session keys on teardown (Damian Mooyman) + * 2018-02-06 [660dfd34a](https://github.com/silverstripe/silverstripe-framework/commit/660dfd34a828e7eb7dc8ef9986b201a14620d17f) Issue where default admin has no password encryption (Daniel Hensby) + * 2018-02-05 [28ca11dd7](https://github.com/silverstripe/silverstripe-framework/commit/28ca11dd7e5e9a1c4fd1f5d4acbec856adfb7176) Regex range identifier correctly escaped (Daniel Hensby) + * 2018-02-04 [1ff32b3](https://github.com/silverstripe/silverstripe-admin/commit/1ff32b347911c1a6f8521f31e79131db68ed3084) Ensure lang is detected from html tag (Martin P) + * 2018-01-26 [416915b08](https://github.com/silverstripe/silverstripe-framework/commit/416915b08248285083518850ad8d015ca8ed25c2) tableName is blank in CompositeDBField->addToQuery (Dominik Beerbohm) + * 2018-01-25 [cf69d0486](https://github.com/silverstripe/silverstripe-framework/commit/cf69d048665befa90eb43146f86cde984b876b3a) Fix ping including requirements (Damian Mooyman) + * 2018-01-24 [c2cd6b383](https://github.com/silverstripe/silverstripe-framework/commit/c2cd6b3832c6bc4775b2742df593b445c2aca391) Fix Member_GroupSet::removeAll() (fixes #3948) (Loz Calver) + * 2018-01-24 [f2b4c192e](https://github.com/silverstripe/silverstripe-framework/commit/f2b4c192ec4d70779f7c667a976e741a7f3a26c5) Fix UploadField cuts off “Save” button (closes #2862) (Loz Calver) + * 2018-01-23 [7384e3fc2](https://github.com/silverstripe/silverstripe-framework/commit/7384e3fc25987742ea08af74b704857a936e8ec0) Gridfields with dropdowns having lots of overflow (Scott Hutchinson) + * 2018-01-19 [5849820](https://github.com/silverstripe/silverstripe-asset-admin/commit/58498200190cba086477c158d1fe6112cf3b0a1e) Fix compatibility issue with chromedriver (Damian Mooyman) + * 2016-10-21 [8e5bb6fbd](https://github.com/silverstripe/silverstripe-framework/commit/8e5bb6fbdce0b2ca2d08a45534df2264db5e6b12) Fix : relObject() should return null if one of the node is null (Jason) + * 2016-03-15 [22b3a71ec](https://github.com/silverstripe/silverstripe-framework/commit/22b3a71ec0c8cd8c38030fa0bf5449abefafe8a3) fixing val reference to url in https hotlink (Denise Rivera) + * 2015-04-22 [1f63637b9](https://github.com/silverstripe/silverstripe-framework/commit/1f63637b9369d4644a92523ada5d1a5dc0576c12) for #4095, TinyMCE not able to modify props of embed media (bug 1) and invalid HTML inserted (bug 2) (Patrick Nelson)